I agree you could do the same with reduce if you’d prefer that. I prefer the shorter version, but that’s why it’s good there are many ways to do the same thing. I wouldn’t call JavaScript “insane” because it does some things differently.
In your example, you probably want to use Number.NEGATIVE_INFINITY instead of 0 as the initial value in case there are only negative values in the array.
In your example, you probably want to use Number.NEGATIVE_INFINITY instead of 0 as the initial value in case there are only negative values in the array.
You can just pass it a single argument. I tried that at first but changed it because I thought that was causing my error, but then I figured out it was actually reduce passing additional garbage to Math.max.
I wouldn’t call JavaScript “insane” because it does some things differently.
It's not that it does things differently that makes insane. It's the fact that it does things differently in insane ways. Passing random stuff nobody wanted to the combining function in reduce is one such thing, but there's many many more.
I think you're picking a hole in JS where there isn't one, except, perhaps, in the Math.max function. You could easily create a function which will work very happily with reduce:
Nice alternative! That is the way I used to do this before the spread operator. Works just as well.
You might want to safeguard this with Number.NEGATIVE_INFINITY as the initial value in reduce in case of an empty array. Math.max() also returns -Infinity when called without any parameters.
I think you're picking a hole in JS where there isn't one
There definitely is. The problem here is a clash between two good intentions:
Allowing more than two arguments in the max function
Passing extra information to the combining function
The first one is unnecessary. It's only a bit more convenient to write max(a, b, c) than [a, b, c].fold(max), but it's still something that makes sense.
The second one, on the other hand, is a giant footgun. It only makes sense in the context of optimization, as using map first would result in one temporary array being created, but that should be optimized by the language runtime via stream fusion, not by the specification of the function. Ultimately it will just lead to more confusing code full of functions that do too many things at once, giving it a very procedural feel.
As for your solution, that's basically what I did, except that I wrote the function inline. Another solution would be:
The first one is unnecessary. It's only a bit more convenient to write max(a, b, c) than [a, b, c].fold(max), but it's still something that makes sense.
I'm sure there are many situations where it's preferable to pass multiple arguments instead of constructing a whole new array to do max. I may find it preferable today to construct an array and use array methods to manipulate it, but those methods are, relatively speaking, very new additions to the language.
Regarding:
Passing extra information to the combining function
I've not yet used a language which doesn't allow providing a seed value into its reduction function. Haskell's foldr requires it. Cloure's reduce allows it. C#'s Aggregate allows it to be specified. I wouldn't want to work with a language that didn't allow me to specify a seed value this way.
I appreciate that I wrote basically the same code example that you did - I was trying to point out that there's not any issue at all with reduce in js, it just isn't called fold.
I've not yet used a language which doesn't allow providing a seed value into its reduction function
The seed value is not the problem here. The combining function should take two arguments, but reduce passes 4, which is both dumb and the cause of this problem. I haven't seen another language that does this.
I was trying to point out that there's not any issue at all with reduce in js
Well, there is: it passes two extra arguments to the combining function, which no other fold function usually does.
Ah I see your point now, sorry I misunderstood what you were saying originally, my bad.
It is frustrating, but really we're talking about edge cases here where you're looking to pass variadic functions into Array.reduce. In this instance we're hitting a problem due to the fact that, firstly, Math.max is variadic and secondly that Array.reduce passes additional arguments by default. Agreed that neither of those is ideal.
JS really isn't a language of ideals, though - it's a pragmatic scripting language, and, for all its flaws, it allows people to get things done quickly. For me a big part of being a good JS programmer is learning to live with its flaws, because if you obsess over them, you can't get very far with it.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
In any sane programming language, you'd just do
but alas, JS masterfully breaks every existing pattern except those coming from C.
I agree you could do the same with
reduce
if you’d prefer that. I prefer the shorter version, but that’s why it’s good there are many ways to do the same thing. I wouldn’t call JavaScript “insane” because it does some things differently.In your example, you probably want to use Number.NEGATIVE_INFINITY instead of
0
as the initial value in case there are only negative values in the array.You can just pass it a single argument. I tried that at first but changed it because I thought that was causing my error, but then I figured out it was actually
reduce
passing additional garbage toMath.max
.It's not that it does things differently that makes insane. It's the fact that it does things differently in insane ways. Passing random stuff nobody wanted to the combining function in
reduce
is one such thing, but there's many many more.I think you're picking a hole in JS where there isn't one, except, perhaps, in the
Math.max
function. You could easily create a function which will work very happily with reduce:Nice alternative! That is the way I used to do this before the spread operator. Works just as well.
You might want to safeguard this with Number.NEGATIVE_INFINITY as the initial value in
reduce
in case of an empty array.Math.max()
also returns-Infinity
when called without any parameters.That'd surely be worth doing, I really only added that code to give an example close to the code that was quoted.
Fair enough. 👍
There definitely is. The problem here is a clash between two good intentions:
The first one is unnecessary. It's only a bit more convenient to write
max(a, b, c)
than[a, b, c].fold(max)
, but it's still something that makes sense.The second one, on the other hand, is a giant footgun. It only makes sense in the context of optimization, as using
map
first would result in one temporary array being created, but that should be optimized by the language runtime via stream fusion, not by the specification of the function. Ultimately it will just lead to more confusing code full of functions that do too many things at once, giving it a very procedural feel.As for your solution, that's basically what I did, except that I wrote the function inline. Another solution would be:
Which, to prevent monkey-patching, sadly loses the method-syntax which makes chaining easier to read.
I'm sure there are many situations where it's preferable to pass multiple arguments instead of constructing a whole new array to do max. I may find it preferable today to construct an array and use array methods to manipulate it, but those methods are, relatively speaking, very new additions to the language.
Regarding:
I've not yet used a language which doesn't allow providing a seed value into its reduction function. Haskell's foldr requires it. Cloure's reduce allows it. C#'s
Aggregate
allows it to be specified. I wouldn't want to work with a language that didn't allow me to specify a seed value this way.I appreciate that I wrote basically the same code example that you did - I was trying to point out that there's not any issue at all with reduce in js, it just isn't called fold.
The seed value is not the problem here. The combining function should take two arguments, but
reduce
passes 4, which is both dumb and the cause of this problem. I haven't seen another language that does this.Well, there is: it passes two extra arguments to the combining function, which no other fold function usually does.
Ah I see your point now, sorry I misunderstood what you were saying originally, my bad.
It is frustrating, but really we're talking about edge cases here where you're looking to pass variadic functions into
Array.reduce
. In this instance we're hitting a problem due to the fact that, firstly,Math.max
is variadic and secondly thatArray.reduce
passes additional arguments by default. Agreed that neither of those is ideal.JS really isn't a language of ideals, though - it's a pragmatic scripting language, and, for all its flaws, it allows people to get things done quickly. For me a big part of being a good JS programmer is learning to live with its flaws, because if you obsess over them, you can't get very far with it.