# considered harmful [was C++11 lambdas]
Bob Foster
bobfoster at gmail.com
Mon Mar 15 15:27:40 PDT 2010
Harmful because it's unpleasant to look at and leads to indecipherable
code. Every time someone proposes adding another #, the syntax gets
uglier and less readable.
I apologize for coming to this point rather late, but frankly once I
read the # proposal and realized no one intended to implement actual
closures, I decided the whole project was a plot to convert Java
programmers to Scala and my mind turned to more pleasant things. This
was a mistake, and Remi Forax's excellent counter-proposal has
inspired me. Why _not_ try something simpler?
I have a (very) few nits to pick with Remi's proposal:
- int(int) is a function type, not a function.
- the . has no place in function call syntax; functions are not methods.
- I quite like the ( expr ) syntax when a function body is only a
single expression, but it's not essential and if it were adopted
should be extended to methods for consistency.
- Java doesn't have type inference elsewhere, so it seems inconsistent
to have it for functions. However, if it was going to be part of the #
syntax, it should be allowed here, too, as Remi originally proposed,
and extended to methods, as well.
The whole proposal works syntactically because currently the
construction Type() never appears in a valid program except after new.
So as long as new doesn't pollute anonymous functions (a separate
thread), function types are unambiguous to both the compiler and
readers.
A few examples:
> A method that takes two function types and returns a lambda:[rewritten as]
int(int,int) filter(int(int) filter, int(int,int) operation) {
return int(int x, int y) {
return operation(filter(x), filter(y));
}
}
Used with anonymous functions:
int(int,int) f = filter(int(int i) { return i % 2 == 0 ? i : i/2*2;},
int(int x, int y) { return x*y;});
If you wanted to allow type inference for return types, it would look like:
int(int,int) g = filter((int i) { return i % 2 == 0 ? i : i/2*2; },
(int x, int y) { return x*y; });
If you wanted to allow type inference and the parenthesis syntax:
int(int,int) h = filter((int i)( i % 2 == 0 ? i : i/2*2 ), (int x, int
y)( x*y ));
(It's really hard not to like that, but see comment above.)
A named function, not a method, inline or in a class:
int(int,int) max = int(int x, int y) { return Math.max(x, y); }
An anonymous function:
Thread t = new Thread(void() { doSomething(); doMore(); });
The curry thing seems a bit of a botch at the moment. Surely it's a
partial application, so the syntax should reflect that, and it should
work for methods.
class A {
void foo(int x) { ... }
void(int) fun = { ... }
}
// curry examples
A a = new A();
void() f1 = a.foo(2) curry;
void() f2 = a.foo() curry;
void() f3 = A.fun(2) curry;
f1();
f2();
f3();
To curry an anonymous function:
int(int,int) fc = filter((int i)(<as above>), (int x, int y, int
z)(Math.max(Math.max(x,y), z)(0) curry);
assert fc(2, 5) == 4;
assert fc(-2, -5) == 0;
Bob
On Sun Mar 14 09:14:29 PDT 2010 Rémi Forax forax at univ-mlv.fr wrote:
> Yes, seeing that I wonder if we are not going in the wrong direction by
> trying
> to protect lambda and function type by a # or some enclosing parens.
>
> Why not trying something simpler ?
>
>
> A function that takes an int and returns an int:
> int(int)
>
> A function that takes an int and returns nothing:
> void(int)
>
> A function that takes two ints and returns an int:
> int(int, int)
>
> A function that throws an Exception:
> int(int) throws Exception
>
> A function that takes a function that throws an Exception:
> int(int(int) throws Exception)
>
> A function that throws an Exception and takes a function
> int(int(int)) throws Exception
>
> A function that takes an int and returns a function that returns an int
> int() (int)
>
> curry!
> R() throws E (R(A) throws E, A) curry = ...
>
> Grammar:
> ResultType ( TypeList ) throws ExceptionList
>
>
> And removing the # in the lambda syntax:
>
> int(int) fun = (int x) (x); ?// lambda expression
> int(int) fun = (int x) { return x; }; ?// lambda block
>
> A method that returns a lambda:
> int(int,int) plus() {
> ? return (int x, int y) (x+y);
> }
>
> A method that takes two function types and returns a lambda:
> int(int,int) filter(int(int) filter, int(int,int) operation) {
> ? return (int x, int y) {
> ? ? return operation.(filter.(x), filter.(y));
> ? };
> }
More information about the lambda-dev
mailing list