-
Notifications
You must be signed in to change notification settings - Fork 294
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
Reduce returns an array, not a value #44
Comments
@aeisenberg The clarification would then be something like, NOTE: The ES5 spec has reduce return a single value instead of an array with a single value. You can ignore this difference for now, but our reduce behaves this way for the same reason you are forbidden from using bracket array access notation. I could also be totally wrong. @jhusain ? |
👍 |
@MrNice Can you please explain "our reduce behaves this way for the same reason you are forbidden from using bracket array access notation." Great comment BTW, it inspired me to dive into the Array object a bit and clarify my understanding: https://tonicdev.com/webxl/array-return-types/ Feedback welcome! |
@webxl I completed an old version of this tutorial, which forbid the use of ES5 reduce doesn't allow chaining: You can get around this limitation by forcing the reduce accumulator to be an array containing the value you're accumulating: // Summation that can be chained
[1, 2].reduce(function(acc, val) {
acc[0] = acc[0] + val;
// but the reducing function MUST return an array
// So the abstraction is very leaky
return acc;
}).map(function(val) {
// Doubling because we can
return 2 * val;
}); // Returns 6 And we dislike leaky abstractions. The reason we want to abstract over the container is simple: we want to be able to have different, more specialized containers than arrays. Observables are containers where elements are ordered like arrays, but instead of being available positionally, they're available over time. You can implement I wonder what a tree over time looks like / is good for... Let me know if that helps! We're trying to lay solid abstractions over familiar concepts, so that we can get away from the machine and into the land of thought stuffs. |
My code above doesn't work because I forgot how reduce works >.<. [1, 2].reduce(function(acc, val) {
// Without using a default array start value EVERY TIME, we must do this check
if (Array.isArray(acc)) {
acc[0] = acc[0] + val;
} else {
acc = [acc + val];
}
// but the reducing function MUST return an array
// So the abstraction is very leaky
return acc;
}).map(function(val) {
// Doubling because we can
return 2 * val;
}); // Returns [ 6 ] Note the other form is this: [1, 2].reduce(function(acc, val) {
acc[0] = acc[0] + val;
return acc;
}, [0]).map(function(val) {
return 2 * val;
}); // Returns [ 6 ] I find that hunting for missing |
@MrNice Thanks for that explanation. I've only ever worked with this definition: "The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value." I get your concerns with leaky abstractions, but I think it's confusing to reactive newbies like me if that definition above has changed to mean something else. Do you know the origins of reduce? Why not call the array-returning version fold? When I think "fold", like a folding fan, all portions of the paper are collapsed to the same 2d area, but there's still some characteristics of the expanded fan. While not very different, "reduce" might be forever associated with the " to a single value"/ map-and-reduce (in that order only) usage. |
@webxl Let's back up a bit Your The entire goal of this walkthrough is to introduce a new data type, the observable. The observable is interesting because it's a JS data type implemented in JS, while many JS programmers just use the 8 or so that every JS engine has (:heavy_plus_sign: the jQuery monad :stuck_out_tongue_winking_eye:). The observable is powerful because it allows you to compose (through pipelining) value transformations over time. Importantly, these compositions are simple to build, read, and analyze, simply because they use a monadic chaining API - every method call returns an observable, all observables implement the same methods, so you can chain method calls together to make a single observable that is influenced by all of the previous behaviors. That's a lot to grok, so the tutorial starts with the common JS array, and leads you through building out the foundational knowledge you need to feel comfortable with the observable interface. The first step of which requires implementing a reduce method. Technically, all a reduce operation has to do is turn a logical collection (set of similar elements) into a single element. But if we want to be able to pipeline these operations, then the method has to return the same type it acts upon, an array. In order to get the final value, you just need to access the data, which in this case looks like We are allowed to diverge in our implementation because we're really chasing after the abstraction. We just want to understand the concept of reducing well enough that we can talk about observables, and the fewer conceptual differences, the easier it is to follow along. Now, about fold vs reduce... They are synonyms, and most languages use the word reduce. As far as I can tell from looking at which languages implemented fold / reduce and when, it appears that it was first named Most of the time, the order of data inputs doesn't matter during a reduction operation (unless the data isn't timestamped on its own and you're doing something like a trending feed, or your operation isn't associative, like exponentiation). So reducing a shuffled collection should return the same value. More mathy / typey languages care about being very precise. When you reduce an array, you do so by folding. This folding operation then has a direction, left or right. This provides the most clarity to the programmer, and has an excellent visual metaphor, whereas reducing is a chemistry / cooking metaphor. |
This was mentioned in comments of other issues, but I think it warrants it's own issue. The
reduce
implementation in the tutorial returns an array, not an object, which goes against the JS spec. For those people coming to this tutorial who are already familiar with JavaScript, this is more than a little confusing.I'd recommend either:
Great tutorial! Lots of fun to go through the exercises.
The text was updated successfully, but these errors were encountered: