top | item 39959831

(no title)

bPspGiJT8Y | 1 year ago

I don't really understand the distinction between "multi-arity" and "unary" functions. In my mental model, all functions are unary, it's just that in "traditional", non-FP languages it's more common to pack arguments into tuples. That is `(a, b, c) => ...` in JS is a unary function which takes a tuple of 3 items. But the thing is, FP has tuples too (and in Haskell, with pretty much the same syntax), it's just that most of the time arguments aren't packed into tuples.

So could you elaborate to me where the distinction lies here and why is there a need to "simulate" things?

discuss

order

jraph|1 year ago

Say you are dealing with a callback mechanism that takes a function and (only) one value to pass:

   function c(f, v) { ... f(v) ... }

But what you actually need this callback mechanism to call is a function that takes two arguments. No default values.

    function f2(a, b) { ... }
There's no way in js that c is going to call f2 and set its b parameter to something. You can't set v to be a tuple so b will be filled:

    c(f2, "value") => b will be undefined.

    c(f2, [1, 2]) => a will be set to [1, 2].
you need to wrap f2 for this when calling c:

    function wrapf2(b) { return f2("fixed a", b) }
Or you can make c deconstruct v, or use apply:

    function c(f, v) { ... f(...v) ...  }
    function c(f, v) { ... f.apply(null, v) ...  }
but then v always needs to be an array:

    c(f, [1])
    c(f, [1, 2])

    c(f, 1) // fails
This is why in Javascript, multi-arity is different from unary with tuples. JS doesn't have tuples as a primitive / first-class type anyway. In some math notations we don't make the difference, but in most programming languages there's a distinction. Your model where functions are always unary but can take tuples, and (v) is the same as v, is correct (and useful when the distinction doesn't matter and is just annoying to deal with), but doesn't match the way many programming languages actually work. I believe even in most functional programming languages, (v) is different from v, you also said it.

In assembly, different parameters are in fully separate registers or stack entries. Interestingly, you could imagine representing tuples as C structs (that can have only one member) and always pass structs, and passing a one-member struct will actually have the exact same effect as passing a value of a primitive type.