Syntax poll
Brian Goetz
brian.goetz at oracle.com
Fri Jun 10 12:53:57 PDT 2011
Greetings lambdenizens;
The EG has started taking up the beloved issue of syntax. At this
point, we'd like to engage the lambda-dev community in a quick, informal
poll.
The goal here is to get a sense of whether there is an obvious overall
preference on the general form. (There are rules, so please read to the
end before responding.)
Of the dozens of proposed syntaxes, there are a few that seem credible.
There are lots of niggly sub-issues, like thin arrow vs fat arrow,
syntax of method references, and others, but for now, we're looking to
fix the high-order bit.
OPTIONS
-------
1. The "strawman" syntax. The original strawman syntax looked like
#(arglist)(expr)
and
#(arglist){ statements }
Example:
list.filter( #(Foo t)(t.length() > 3) )
.map( #(Foo t)(t.barCount) )
.max();
The primary rationale here seems to be that if you pronounce "#" as
"lambda" or "method", it reads like a method literal. It is also the
easiest to parse.
Sensible syntactic simplifications of Strawman include:
- Always using {} regardless of expression-lambda vs statement-lambda
( #(t){t.barCount} );
- Eliding the empty parameter list for nilary lambdas ( #{ 4 } instead
of #(){ 4 } ).
2. The "BGGA" syntax. Here, lambdas are brace-delimited with an arrow
separating the argument list and body: { args -> body }. (Originally
BGGA used the fat arrow (=>) instead of thin arrow (->), but people seem
to almost universally prefer the latter.)
list.filter( { Foo t -> t.length() > 3 } )
.map( { Foo t -> t.barCount } )
.max();
Note that this is what Scala and Groovy do, and people who program in
these languages seem to like it just fine, so there is some actual
evidence that this form is not silly. Sadly there is no room for a
special form for nilary lambdas, so these have to look like { -> body }.
It would be possible to allow (or even require?) parentheses around
the argument list.
3. The "SotL" syntax. This is, basically, the BGGA syntax with a #
glued on the front. Primary advantage: it screams "I am not just a
block". Primary disadvantage: the screaming. Admits a special nilary
form #{ body }. It would be possible to allow (or even require?)
parentheses around the argument list.
list.filter(#{ Foo t -> t.length() > 3 } )
.map(#{ Foo t -> t.barCount } )
.max();
4. The "Redmond" syntax. Here, a lambda is an expression that combines
an argument list and a body with an arrow: (args) -> { body }.
list.filter((Foo t) -> { t.length() > 3 } )
.map((Foo t) -> { t.barCount } )
.max();
All these forms admit inference of lambda formals.
GUIDELINES
----------
Here are some guidelines that might help in evaluating the alternatives:
- Delayed evaluation is a new feature that Java hasn't had before.
Closures should look a little different, but not crazily so. (For
example, for some people the # is the right level of obvious, and for
others it feels like a whack over the head.)
- Aesthetics count, but remember that aesthetics are also highly
subjective. Aesthetic concerns should be evaluated in the context of
real code examples, not in a vacuum. Many syntaxes look very different
in the context of real examples than they do by themselves. Don't let
how it looks by itself guide your opinion, since there will be no
programs where lambdas appear by themselves.
- Familiarity. This counts, but please, sit on your instinct to say
"that just doesn't look like Java." NONE of these will look like Java
at first (until one of them is Java, and then it will look exactly like
Java.) However, confusion for existing forms (such as "this looks like
a cast") is an entirely reasonable basis to not prefer one of the forms.
- It seems desirable for the expression-ness of the lambda expression
to jump out at you and say "I am a lambda expression", especially for
small lambdas. Some people find some of these forms hard to see as a
single expression.
- A lambda should look good at multiple arities. Some forms admit a
special nilary form, some don't. Parentheses around short argument
lists might look like noise, but around long argument lists often add a
desirable grouping. Bear in mind that most lambdas will likely have
relatively small arities (Runnable: 0, Predicate/Block/Mapper: 1,
Comparator: 2).
RULES
-----
1. Resist the urge to respond on-list. (There will be other
opportunities.) Common reasons to be tempted to respond on-list include:
- "Have you considered syntax Z?" (Not the goal of this exercise.)
- "I like A better than B because..." (This will only (a) bias the
opinions of others and (b) start long conversations, which is not the
goal of this exercise.)
- "What you call BGGA isn't because they used the fat arrow." (The
goal of this exercise is a gut-level response.)
2. You can cast a ballot at: http://www.surveymonkey.com/s/BQQLZQM.
The ballot has a line for each option, where you can rate it from "hate
it" to "love it". You must vote on each line. There is also a
free-form box in which you can express opinions. I will publish the
results on-list, so don't say anything you don't want published. Names
are optional.
3. Before voting, please write some code examples in each form based on
real code that uses inner classes, ideally with a few different arities.
Really! This should take no more than 20m, a small price to pay to
have some input, and will greatly increase the quality of the data.
4. We'll leave the survey open until end of business Wednesday, Pacific
time. (Limited to 100 respondents; I'll clone the survey if we get more
responses than expected.)
Thanks for your help!
More information about the lambda-dev
mailing list