Re:Ante: A low-level functional language
by momentoftop on Saturday June 18, 2022 @01:31AM
(#31787461)
It'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.
Most 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?
No 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)
My 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.
OCaml and Haskell parse `a b c d e f` as `((((a b) c) d) e) f`.
And 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.
I 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
> 3I don't understand your objection, what output would you like to see instead?
GP'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
Ah! Right. It helps to have all functions be of arity 1 to disambiguate, yes.
Many counter examples to this, xargs for one.
xargs 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.
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.