4 ms·
I've heard this argument before, but this isn't true. In shell, f x y z, x y z are all augments to f. Doesn't matter if f takes one argument, all are passed to
by georgyo 4y ago
I've heard this argument before, but this isn't true.
In shell, f x y z, x y z are all augments to f. Doesn't matter if f takes one argument, all are passed to the function.
With many functional languages this gets very confusing. IE what ie what does `f f x` do? In shell I know for sure.
In the example f f x, it might be easy to parse. But in f x y z, any of x y z might be functions.
- nemaar 4y agoMost functional languages parse a b c d e f as a(b, c, d, e, f), it does not matter what b, c, d, e, f are. Do you know any language where this is different?
- georgyo 4y agoI thought more languages did this but at least nix and ocaml do not actually behave like I thought. In Ruby however it is a bit more ugly def f x x + 1 end puts f f 1 > 3
- the_af 4y agoI don't understand your objection, what output would you like to see instead?
- lgessler 4y agoGP's point is that while yes, we know since `f` has arity 1 there's no ambiguity, in general you might not have the arity of any given function fresh in your head, and therefore can't tell (in Ruby) just from looking at `f f 1` whether it means a single invocation of an arity 2 function, or two invocations of an arity 1 function
- the_af 4y agoAh! Right. It helps to have all functions be of arity 1 to disambiguate, yes.
- dwenzek 4y agoOCaml and Haskell parse `a b c d e f` as `((((a b) c) d) e) f`.
- jerf 4y agoAnd while different than Algol-descended languages, I don't think that's particularly confusing. (Not that you were saying so, just continuing the conversation.) You can put together a confusing expression with it, but I can put together confusing things with the Algol syntax with not too much effort too. I've got the source code with my name on the blame to prove it.
- tomp 4y agoNo functional languages do that. OCaml parses a b c as ((a b) c). In case the compiler can determine that a is a function taking 2 arguments, it will optimise the code, so that it’s effectively a(b, c). But in general, that’s not possible, especially in the case where the compiler determines that a is a function with a single argument (in which case, it’s return value must be another function, which is in turn called with c) or when a is a first-class function (e.g. passed as an argument)
- sfvisser 4y agoMy toy FP language did. :) It’s perfectly possible to just parse a list of arguments and figure out currying in a later compiler stage. In my experience it even somewhat helps with producing nicer arity-specific error messages, which user might appreciate.
- zeckalpha 4y agoMany counter examples to this, xargs for one.
- georgyo 4y agoxargs is not a counter example. It is not a shell builtin, it is a program that takes a bunch of string arguments like every other program a shell would call. xargs -0 -n1 bash -c 'mv $1 ${1//.js/.ts}' -- Everything to the right of xargs is a string argument passed to xargs.
- zeckalpha 4y agoSo an identifier representing a function? Isn’t that the same for most languages?
- momentoftop 4y agoIt's pretty easy to reason about that particular example if you have a type system. In a simply typed language, "f f x" is just a type error, so it doesn't do anything. In the polymorphic lambda calculus, the typing will force f to either be the identity, meaning that "f f x = x", or it will be a constant function, so you just replace "f f" with the constant.