I get the entire logic of the reduce method, and rest parameter, however I really don't get the importance of 0. Thank you very much in advance!
const sum = (...args) => {
return args.reduce((a,b) => a + b, 0);
}
I get the entire logic of the reduce method, and rest parameter, however I really don't get the importance of 0. Thank you very much in advance!
const sum = (...args) => {
return args.reduce((a,b) => a + b, 0);
}
ECMAScript is a dynamically typed / untyped / uni-typed programming language (depending on whom you ask). However, it still makes sense to look at the types of
Array.prototype.reducehere.I am going to use TypeScript syntax, in fact, I am going to use the definition from the TypeScript library, but the actual syntax doesn't really matter:
The fact that the original array and the current index are passed into the callback function is an ECMAScript oddity that is not really necessary to understand how
reduceworks, so let's get rid of those:Note also that we have two different type parameters here:
Tis the element type of theArray<T>.Uis the result type ofreduce.So,
reduceis a function which takes three arguments:this, which is theArray<T>it iterates over.Uand aTand produces a newU.U.Conceptually, what
reducedoes is that it "reduces" a collection of values down to a single value. It is important to understand that this single result value can have an arbitrary type. It does not have to be the same type as the element type of theArray.reducedoes this using the reduction function that is passed to it.So, conceptually what
reducereturns isOr, if we write the callback function as a binary operator
ω:Note that the callback function must be left-associative, i.e. equivalent to
Many collections libraries, and ECMAScript is no exception, also provide a version of
reducethat does not have an initial value. In many libraries, this version has a different name (for example, in Scala, the version with initial value is calledfoldLeft, the version without is calledreduceLeft, in Haskell, the version with initial value is calledfoldl, the version without is calledfoldl1). In ECMAScript, this is instead handled via "overloading", i.e. you can simply leave out theinitialValueargument.If the initial value is left out, we instead start off with the first element of the collection, i.e.
or written as an operator
This has an important consequence, though! Our operator / callback function now needs to take two
Ts and return aT, there is no longer a way to have a result type that is different from the element type.And it has another important consequence:
reduceno longer works with an empty collection.So, these would be the two reasons why you would need to supply an initial value:
reduceto work with an empty collection.In this particular case, the first reason does not apply: the function is clearly meant to reduce an
Array<number>tonumber. But the second reason is relevant: you don't want to force clients of the function to have to check whether or not the collection is empty. A client should be able to calland not worry whether
someArrayis empty or not.The ability to change the type to an arbitrary type is important for the universality of
reduce. It turns out thatreduceis a powerful function: it can do everything you could do by iterating over a collection. In other words: you could remove every method ofArray.prototypeexceptreduce, and also removefor … ofandfor … infrom ECMAScript, and you could still do everything you could possibly do by iterating over a collection. (Well, you'd need a way to add something to an array, I guess, so let's keeppushas well.)Here is just an example of implementing
Array.prototype.mapusingArray.prototype.reduce:Here you see that the fact that we can change the type is important, because we start with an
Array<T>, but we don't want aTas a result, we want anArray<U>. This also shows that the statement "reducereduces the collection down to a single value" does not mean that the result has to be a simple value. The result value can be as complex as you like … in this case, another array.