News for hackers. Stuff that matters.
Re:Don't use functions as callbacks unless they're designed ... by schwartzworld on Saturday February 06, 2021 @06:43AM (#26045919)
If your code has tests, an API change like the one described in the article would get caught immediately.

And it only works because `Array.prototype.map` callback has one required arguments and two optional ones. What language with optional function arguments protects you from this sort of behavior? Do people in that language not test this sort of behavior? Or at least run through the app?

More than that, the whole hurrdurr-javascript-bad thing is so tired. Lots of work is being done in JavaScript. Sure, it has its quirks, but those quirks come with expressiveness. You can use functional or imperative style, throw lambdas around, and it runs on pretty much all the phones and computers in the world.

Re:Don't use functions as callbacks unless they're designed ... by mhh__ on Saturday February 06, 2021 @07:45AM (#26046157)
If you have a good type system you don't need to write tests like this. I test my algorithms not my function calls.

Also, > A lot of work is being done in JavaScript

Is that it? It's one of the best funded languages on Earth, what do you expect - with D for example we can do all the things you mentioned and catch errors like this, and we're basically just some guys working on the language not the combined might of the entire Internet sector.

Re:Don't use functions as callbacks unless they're designed ... by sfvisser on Saturday February 06, 2021 @07:27AM (#26046092)
> What language with optional function arguments protects you from this sort of behavior?

Languages with a sane type system.

TypeScript has no issues catching such mistakes. Writing tests to catch simple type errors is such an incredible waste of time.

Re:Don't use functions as callbacks unless they're designed ... by tom_mellior on Saturday February 06, 2021 @08:07AM (#26046250)
The article has a whole section called "TypeScript doesn't solve this", with examples and stuff. Is it mistaken?
Re:Don't use functions as callbacks unless they're designed ... by sfvisser on Saturday February 06, 2021 @09:30AM (#26046709)
Partially.

TypeScript doesn't complain when you pass in a function that ignores some of its arguments. Which is totally fine and safe. If you upgrade your function from no second argument to a numeric second argument TypeScript will not complain and your program might break.

It will not crash, because it still perfectly type-safe, but it might not behave like you want to. So in that sense the article has a point.

However, this is just one instance of a larger issue with changing the behavior of a function, while keeping the types compatible.

  - Using a function as a callback to .map() with two numeric arguments and then swapping the arguments.
  - Returning a tuple of two of the same type and swapping the order.
  - Returning a string in a new encoding.
  - ...
Basic rule: if it's a type error and the program might crash, TypeScript will complain. If the types are fine and only the behavior changes, TypeScript will (obviously) not complain. Callback functions and optional arguments are not special in this regard.
Re:Don't use functions as callbacks unless they're designed ... by tom_mellior on Saturday February 06, 2021 @10:27AM (#26047151)
Thanks for the explanation.

> If you upgrade your function from no second argument to a numeric second argument [...] It will not crash, because it still perfectly type-safe

It's type-safe using a definition of "type-safe" that is defined relative to the underlying JavaScript model of "corrupt the user's data rather than crash". It wouldn't be type-safe using most other languages' (including Python, for example) model of "functions have a type that includes the number of arguments, and applying them to the wrong number of arguments is meaningless and hence not considered type-safe".

It's fair for TypeScript to use this approach. But it is surprising to many of us, who view type systems as tools for ruling out some dumb functional bugs, not just crashes.

Re:Don't use functions as callbacks unless they're designed ... by macintux on Saturday February 06, 2021 @09:35AM (#26046742)
> It will not crash, because it still perfectly type-safe, but it might not behave like you want to.

Which is generally worse than crashing, because silent data corruption can have far-reaching impacts.

Re:Don't use functions as callbacks unless they're designed ... by giantDinosaur on Saturday February 06, 2021 @07:56AM (#26046207)
Here you go:

  Array.prototype.map = function (func) {
    if (func.length !== 3) {
        throw new Error(
            "bad! this function you've passed must take THREE arguments. Grr!"
        );
    }
    for (let i = 0; i < this.length; i++) {
        this[i] = func(this[i], i, this);
    }
    return this;
  };
;)

(making this workable and bug free is left to the reader or multi-billion dollar corporations)

There can be a non-indexed map as well.

I'm most curious as to who uses the last argument in the JS map function!

Re:Don't use functions as callbacks unless they're designed ... by dragonwriter on Sunday February 07, 2021 @06:50AM (#26054399)
> I'm most curious as to who uses the last argument in the JS map function!

It's convenient for some things that would otherwise require a reduce (but where reduce isn't particularly more efficient, because you just need lookahead/lookbehind) or an imperative loop, like transforming a list to a set of moving averages over the list.

It's a little more expressive than reduce our imperative lots loops in those cases, too.

Re:Don't use functions as callbacks unless they're designed ... by kuschku on Sunday February 07, 2021 @06:37AM (#26054327)
> I'm most curious as to who uses the last argument in the JS map function!

array.map((val, index, {length}) => if (index + 1 == length) { alert("last element") } else { alert("element #"+index) })