Syntax Sugar for Lambdas
The standard form of a lambda expression is a,b -> f a b
or () -> c
for a nullary function. This syntax is syntactic
sugar for the declaration of a child feature of Function
and
creation of one instance at the point the lambda expression is used.
Nevertheless, there are many cases where this syntax is still somewhat awkward and could be shortened further.
Inline functions in other languages
Haskell
Since Haskell uses lazy evaluation by default every expression is
a lambda expression. There is syntax sugar such as (+)
for addition of
numerical values.
TBD: check Haskell syntax sugar
Haskell syntax sugar | verbose | comment |
---|---|---|
do { file <- open "name" ; bytes <- readFully file ; process bytes } |
open "name" >>= (\ file -> readFully file >>= (\ bytes -> process bytes )) |
The do notation is a way to format the code of calls
to |
(+) a b |
a + b |
Operators in Haskell can be used as prefix functions if put in parentheses. |
(+a) |
(\ x -> x + a) |
Operator in parentheses with one argument to one side is interpreted as a unary function with the argument added to the other side. |
(-) a b |
a - b |
Functions with non-alphanumerical names are operators. Placed in parentheses, they can be used like normal function names. |
a `f` b |
f a b |
Functions with alphanumerical names can be turned into operators using back ticks. |
F#
F# provides forward and backward pipes to apply values provided in tuples as missing arguments in partially applied functions.
F# syntax sugar | verbose | comment |
---|---|---|
a |> f x y |
f x y a |
The pipe-operation does not help with lambdas, but with chaining calls.
The pipe-operator is very similar to chaining calls with dots in
object-oriented languages ( |
g |||> f x y |
let (a, b, c) = g f x y a b c |
A pipe can deconstruct a tuple into several arguments that are passed to a function that is called. |
Java
Java's lambda expressions are for Java's standards already very heavy syntax sugar. The additional syntax sugar is limited:
Java syntax sugar | verbose | comment |
---|---|---|
(a,b) -> { f(a,b); } |
(Type1 a, Type2 b) -> { return f(a,b); } |
Java performs type inference for the arguments of a lambda. |
(a,b) -> f(a,b) |
(a, b) -> { f(a,b); } |
|
a -> f(a) |
(a) -> f(a) |
|
Groovy
Groovy has an implicit argument it
which is used for unary lambdas.
Groovy syntax sugar | verbose | comment |
---|---|---|
{ println it } |
{ it -> println it } |
Special handling using |
Lambda Syntax Sugar in Fuzion
Here are some suggestions for possible syntax sugar in Fuzion:
Fuzion syntax sugar | verbose | comment |
---|---|---|
a,b -> f a b |
(a,b) -> f a b |
parentheses are optional |
(+) |
a, b -> a + b |
An infix operator could be abbreviated by just putting it into parentheses. The fact that this has to be an infix operator becomes clear from the type of the field the lambda is assigned to. A function with two arguments means the lambda has to be an infix operator.
Note that the parentheses are required such that the parser can
distinguish the case |
(-) |
a -> -aor a -> a- |
A unary operator could be abbreviated by just putting it into parentheses. The fact that this has to be an infix operator becomes clear from the type of the field the lambda is assigned to: A function with one argument means the lambda has to be a unary operator. The problem is that we do not know at this point if it is a prefix or a postfix operator. The code to lookup the actual feature called must take both, prefix and postfix into account. If one is found, we can take it. If both exist, the code is ambiguous and we must flag an error. |
+expr |
a -> a + expr |
A prefix operator applied to an expression used as a lambda with one argument can be treated as partial application of an infix operator where the argument is the left hand side.
This should also work for numeric literals of the
form |
expr- |
a -> expr - a |
An postfix operator applied to an expression used as a lambda with one argument can be treated as partial application of an infix operator where the argument is the right hand side. |
(.f x y) |
a -> a.f x y |
Applying a dot-call to the single argument of a lambda could be abbreviated using this syntax. |
f x y |
a,b,c -> f x y a b c |
Partial application: A call used as a lambda could be considered a partially applied call. |
arbitrary expression |
() -> arbitrary expression |
Automatic lazy evaluation for expressions that are not assignment compatible to an argument of function type, but assignment compatible to the result of that function type. |
x >>= (.f x y) |
x.bind (a -> a.f x y) |
This would allow chains of the form |