-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add Collection#reduce #1649
Comments
Added Area-Library, Triaged labels. |
This comment was originally written by @seaneagan Oh, I didn't realize the parameters were swapped. Now there will be no way |
That's exactly why it's not optional. There are a few potential default values:
And then, what if there are only one element, should that just be the return value? And would the behaviour then change if a value is given? We could maybe look into adding 'fold' that does what you suggest?
|
This comment was originally written by @seaneagan See http://en.wikipedia.org/wiki/Reduce_(higher-order_function) There are many languages that have a single method with an optional initial http://docs.python.org/2/library/functions.html#reduce There were only a few which use 2 separate methods, one with an initial Haskell ... possibly due to their stronger type systems (e.g. generic methods). |
Reduce was added with map-reduce in mind(http://en.wikipedia.org/wiki/MapReduce). There it's quite rare that the return-value and the list-value is of the same type, making the 'first-value as initial-value'-pattern non fitting in. Looking at the link you sent, the reduce you describe is frequently named 'fold'. Why not use the name 'fold', then both methods could co-exist? |
This comment was originally written by @seaneagan I think functional programming's map and reduce are slightly different than |
This comment was originally written by mailto...@gmail.com Reduce, as far as I know, does what the proposed reduce does when no initial value is given: In Scala, if have rarely used reduce, but I fold a collection into a different type quite often. |
The reduce we have in Dart is an implementation of the classical foldl function on Lisp-like lists (which is pretty much what Iterable corresponds to). It has the advantage over foldr that it runs in constant space. That also means that it can be extra verbose for cases where you you just want to apply a binary operation over the element type to a non-empty Iterable. Or unusable if your binary operations doesn't have a unit. So, I'm not opposed to having a separate function that doesn't take a separate initial value and instead uses the first value, and that necessarily throws on an empty iterable. /L |
This comment was originally written by @seaneagan I think if it has to be different than JavaScript (i.e. 2 separate fold(initialValue, combine(previous, E next)); |
This comment was originally written by mail...@gmail.com I am fine with 'fold' and 'collapse', but as 'reduce' is already established and interpreted in the sense of "map/reduce", it may be worth to keep that. So 'collapse' seems good as an addition, and the name describes what it does IMHO, even in contrast to 'reduce'. But, please, do NOT declare collapse as being the "opposite of expand", as "expand" (also known as 'bind' or 'flatMap' outside Dart) is a totally different beast. Best explained: You can't do mylist.collapse(...).expand(...) as collapse does not result in a list, but a single value, so expand is not defined on the result (except E might be List casually). nor: assert mylist.expand(...).collapse(...) == mylist Please refer to the dart-misc mailing list thread titled "Improving the list API" for following the debate around expand: |
This issue was originally filed by @seaneagan
see http://en.wikipedia.org/wiki/Fold_(higher-order_function)
As with the other higher-order Collection methods, would be good to be consistent with JavaScript method names, and JavaScript has Array#reduce.
Similar to Collection#map (issue #945), this really wants to be a generic method (issue #254). The contract of this method could be something like:
R reduce<R>(R callback(R prev, E curr), [R initial = _somePrivateValue]) {
Iterator iter = iterator();
if(initial === _somePrivateValue) { // initial value not passed
if(!iter.hasNext()) return null; // no items either
initial = iter.next(); // defaults to first item
}
R prev = initial;
while(iter.hasNext()) prev = callback(prev, iter.next());
return prev;
}
The text was updated successfully, but these errors were encountered: