I'm curious about the syntax of lambdas, which like in Haskell requires a \ symbol.
I always asked myself if in theory the language could be designed to represent lambdas without \ without incurring in any ambiguity, i.e., if a -> b
was enough.
I would love to have your take on this.
@Joshua Warner may have thoughts on this :big_smile:
Particularly with multiple arguments, or when using pattern matching in arguments, that will make parsing much more difficult (maybe impossible to parse unambiguously).
Even ignoring the difficulty of parsing, in practice I think this will lead to needing to put parens around the lambda in order to clear up the ambiguity.
I understand it can help readability. But I cannot honestly think of a case where the lack of a prefix symbol could cause ambiguity
can you share an example of an ambigue expression that would cause problems to the parser?
There are a couple cases. You can do pattern matching / destructuring in the arguments to a lambda - e.g. \Foo a b -> a+b
- which both destructures a Foo tag, pulls out the two fields, and then binds those as variables in the body.
Right now you can pass that lambda as an argument to a function like so: myFunc \Foo a b -> a+b
. Without the \
, that becomes: myFunc Foo a b -> a+b
. Is that a function call taking a closure as it's only argument? Or is that a function taking the tag Foo
, the value a
, and a single-argument closure b->a+b
as arguments?
In order to make that unambiguous, you'd have to add parens like so: myFunc (Foo a b -> a+b)
The other case is around lambdas accepting multiple arguments - e.g. \a, b -> a+b
.
This works fine in the context above (passing it as an argument) - but we run into trouble if we have to put that _anywhere inside_ parenthesis.
e.g. (a, b -> a+b)
becomes ambiguous whether you mean a tuple with two fields a
and b -> a+b
, or a parenthesized lambda that takes two arguments. Note that this is true if it's nested anywhere, even deeply inside a parenthesized expression (or a list with []
- same thing).
Also note that there's a closely-related problem around "multi-backpassing" - e.g. a, b <- foo
, that's been discussed before. That doesn't use an introducer like \
, and so has same problems as above.
Currently we resolve this ambiguity by saying you can't ever use multi-backpassing anywhere inside a parenthesized expression - and that's mostly fine because needing multiple "return values" (which are really arguments) is rare.
I don't think it would fly if we made the same restriction on lambdas, particularly given that you're going to have to parenthesize them in some new cases you didn't before (see the first point).
Can't comment on the syntactic necessity, but in practice I find it an invaluable visual marker that lets me mentally parse quickly, especially for anonymous lambdas
Very clear! Thank you very much for the insightful explanations!
Last updated: Jul 06 2025 at 12:14 UTC