-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
group-and-fold implementation #1004
Conversation
TODO
|
Docs for group-and-fold operations Fix implementation for countEach and sumEachBy countEach and sumEachBy implementations for JS Rename keySelector to keyOf Generate additional sources for groupingBy + headers Rename countEach and sumEachBy to eachCount and eachSumOf.
80b5a39
to
16bff4c
Compare
@SinceKotlin("1.1") | ||
public interface Grouping<T, out K> { | ||
/** Returns an [Iterator] which iterates through the elements of the source. */ | ||
fun elementIterator(): Iterator<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@{18f15b45-4413-42a3-82e7-d057983d1e65,Ilya Gorbunov} sourceIterator()
or just source()
? Need to be documented: whether it creates iterator every time or keep the same instance. If the behaviour is undefined we have to notice it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe elementIterator
being a fun
conveys the intent well. If that was the same instance every time, it would be a property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was called source
in the beginning, that I renamed it to iterator
and then to elementIterator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some consideration, sourceIterator
seems to look better.
public inline fun <T, K, R> Grouping<T, K>.aggregate( | ||
operation: (key: K, value: R?, element: T, first: Boolean) -> R | ||
): Map<K, R> { | ||
val result = mutableMapOf<K, R>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we use aggregateTo
instead?
@SinceKotlin("1.1") | ||
public inline fun <T, K, R, M : MutableMap<in K, R>> Grouping<T, K>.aggregateTo( | ||
destination: M, | ||
operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value
vs accumulator
, v
vs acc
fold( | ||
initialValueSelector = { k, e -> kotlin.jvm.internal.Ref.IntRef() }, | ||
operation = { k, acc, e -> acc.apply { element += valueSelector(e) } }) | ||
.mapValues { it.value.element } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as we already use internal API hack we could do even more: we can create replace IntRef
to Int
inplace and then do unchecked cast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't call it internal API hack, because that API is used publicly by the compiler in the generated bytecode.
mapInPlace is possible as JVM-only optimization, otherwise it would make the code non-portable to platforms, where generics are reified.
* using the specified [keySelector] function to extract a key from each character. | ||
*/ | ||
@SinceKotlin("1.1") | ||
public header inline fun <K> CharSequence.groupingBy(crossinline keySelector: (Char) -> K): Grouping<Char, K> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why there is specialization here? the implementations look the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's how the code is generated now.
…ate implementation to aggregateTo.
|
|
|
* they group elements by their keys and then fold each group with some aggregating operation. | ||
* | ||
* It is created by attaching `keySelector: (T) -> K` function to a source of elements. | ||
* To get an instance of [Grouping] use one of `groupingBy` extension functions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line 32 |
---|
"a group" -> "the group" here and below |
|
|
* It is created by attaching `keySelector: (T) -> K` function to a source of elements. | ||
* To get an instance of [Grouping] use one of `groupingBy` extension functions: | ||
* - [Iterable.groupingBy] | ||
* - [Sequence.groupingBy] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
line 61 |
---|
Any chance for some @sample 's? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aggregate
and aggregateTo
are not intended to be used much in user code, they are here more to implement other folding functions when fold
or reduce
do not fit for some reason.
Other functions (fold, reduce, eachCount, etc) will get samples eventually.
|
We're going to rename |
…ameters of lambdas to _.
An implementation of Kotlin/KEEP#23 proposal