Something simpler?
Reinier Zwitserloot
reinier at zwitserloot.com
Wed Mar 17 21:13:31 PDT 2010
I just don't understand how this works. Some syntax doesn't feel right to
someone, and the magic words "This isn't java" are spoken. Is there some
sort of device to measure this property? I'd love to get my hands on a
javometer.
Hm. Let me try a different direction.
"I think Mark Reinhold's strawman proposal does not look like java. It
violates the cardinal rule of language extension: Do no harm".
Now we're even and we can throw both proposals into the dust bin and start
over. Or possibly, we should say that claiming something "doesn't look like
java" and "does harm" is meaningless unless its backed up with more than a
gut instinct.
In an attempt to follow my own advice, I'll retort one of your claims that
you didn't back up: The notion that this syntax "wouldn't be understood" by
a java programmer.
In my defense of Peter's proposed syntax, This is the Reinhold Strawman
syntax way to do it:
#int() two = #()(2);
and this would be the Levart Bracket syntax way:
[:int] two = (:2);
Both look like gobbledygook to someone not familiar with the feature, and
have no clear match in existing java syntax that is somewhat similar to
allow such a programmer to take an educated guess. The poor programmer is
going to have to figure this out from the way they look alone.
In the first case, the "#" is virtually new; the only existing java concept
that involves the hash is that # is used as member delimiter in javadoc
links. Closures have absolutely nothing to do with type members; in the
strawman hashes are used both to identify function types and to create
closures. Neither of which are type members or even roughly analogous to
type members. Furthermore, the #()(2) looks kind of odd and feels like the
first set of parens is optional or a mistake of some sort. In fact, if you
remove all parens and hashes from the first snippet, its legal java, but not
at all what was intended. (int two = 2; - no closure).
In the second case, we have similar problems. There's a colon involved
that's meaningless if you don't know what its for, and array brackets. Array
brackets *around* something that's obviously a type is completely unknown
territory, and, similar to the strawman's hash, gives the casual java
programmer nothing. The one thing where existing java uses them (arrays) has
nothing whatsoever to do with closures, and like the # in strawman, the
placement of those braces means this syntax clearly isn't about arrays.
Again, here, removing the weird symbols ([] and colons) produces legal java
(int two = (2);) that isn't what was intended.
The conclusion then is that you're right. It would indeed not be understood
by a java programmer that has no experience with this concept. However, the
same thing can be said about the strawman syntax!
Thus, they both lose at this 'it feels like java' game. Given that java has
absolutely no concept of closures that don't come with a ridiculous verbiage
(AICs), any proposal that will fit the bill for Project Lambda will likely
lose this game. If this game is to be won, start eliminating concepts. Get
rid of function types - you can probably do without them. Get rid of the
(for java6, at least) crazy amounts of inference, and move towards something
that looks and feels a lot like CICE. Using parens instead of brackets or
vice versa is not going to change the amount of new concepts a programmer
needs to understand. This completely changes the direction of Lambda, but at
least there'd be movement towards something a java programmer not familiar
with the concept might understand just by looking at it.
There's a much, much simpler alternative, though. Stop worrying about
closures being so natural that any java programmer will instantly grok them
even if not familiar with them, and learn to accept that this simply isn't
going to happen. Instead, assume that java programmers will pick up on it,
given time. They figured out generics after a while, they can handle
closures: At first it looks confusing, then they learn a little about it,
and they understand.
It's rather freeing to do this, as now comparing proposals can be done using
much more dare I say sensible requirements:
- How long does it take someone entirely familiar with closures to distill
the intent behind some line of code that involves closures, when looking at
the line? Using the same delimiter (parens) too much is going to make it
very hard to visually match braces.
- How well will it integrate into existing libraries, particularly those
that have had to make do with SAM types to fill their closure needs?
--Reinier Zwitserloot
NB: Osvaldo, your comment about polyglotters is a good one to make, but
programmers who natively think in Objective C are somewhat unlikely to try
out Java (and regardless, ObjC syntax is closer to smalltalk than C, so
switching to java is syntaxwise going to be quite a jump anyway), and in C,
the annotation concept is so different, both in semantics and usage, that I
doubt much confusion will ensue. Fortunately, I doubt a polyglotter is going
to weigh any confusion stemming from this problem heavier than java not
having closures at all, so presumably they'd go easy on java for it.
On Wed, Mar 17, 2010 at 9:10 AM, Joshua Bloch <jjb at google.com> wrote:
> I don't want to be the party pooper here, but this doesn't look at all like
> Java. I'm afraid it violates the cardinal rule of language
> extension: primum nil nocere.
>
> Josh
>
> On Tue, Mar 16, 2010 at 4:13 PM, Peter Levart <peter.levart at gmail.com
> >wrote:
>
> > In light of recent Remi Forax's plea for simpler syntax, in light of of
> '#'
> > and '.(' considered
> > harmful, in light of Neal Gafter's blog about desirable orthogonality of
> > language features:
> >
> >
> >
> http://gafter.blogspot.com/2006/09/failure-of-imagination-in-language_17.html
> >
> > and above all in light of Lawrence Kesteloot's writing:
> >
> > http://www.teamten.com/lawrence/writings/the_language_squint_test.html
> >
> > which extends "orthogonality" to syntax as well, here's my 3rd attempt at
> a
> > simpler syntax:
> >
> >
> > FunctionType:
> > '[' ParameterTypes_opt ':' ResultType Throws_opt ']'
> >
> > ExpressionLambda:
> > '(' ParameterList_opt ':' Expression ')'
> >
> > StatementLambda:
> > '{' ParameterList_opt ':' Statements '}'
> >
> > FunctionInvocationExpression:
> > FunctionTypedExpression '[' ExpressionList_opt ']'
> >
> >
> > examples:
> >
> >
> > [:int] two = (:2);
> >
> > assert two[] == 2;
> >
> >
> > [File:String throws IOException] readFile = {
> > File f:
> > Reader in = new FileReader(f);
> > try {
> > char[] buf = new char[8192];
> > StringBuilder sb = new StringBuilder();
> > int nread;
> > while ((nread = in.read(buf)) >= 0)
> > sb.append(buf, 0, nread);
> > return sb.toString();
> > }
> > finally {
> > try { in.close(); } catch (IOException e) { // ignore }
> > }
> > };
> >
> > String text = readFile[new File("/etc/passwd")];
> >
> >
> > [[A:R throws E], A : [:R throws E]] curry = ([A:R throws E] lambda, A arg
> :
> > (:lambda[arg]));
> >
> > [[A:R throws E], A : [:R throws E]] curry2 = {
> > [A:R throws E] lambda, A arg :
> > return (:lambda[arg]);
> > };
> >
> > [A:R throws E] lambda = {
> > A a:
> > if (a == null)
> > throw new E();
> > return new R(a);
> > };
> >
> > [:R throws E] curried = curry[lambda, new A()];
> >
> > R r = curried[];
> >
> >
> > discussion:
> >
> >
> > I know, I know, '[]' are reserved for arrays. But so are '()' - for
> > expressions,
> > method/constructor params and casts. The point is that '()' are very much
> > abused in current 0.15
> > lambda proposal for function types as well as lambdas (just look at
> > expression lambda
> > potentially containing 3 pairs of '()' in single construct). Lambda and
> > function-typed heavy
> > code is starting to look like Lisp - not very Java like. The point that
> > Lawrance Kesteloot
> > beautifully explains in his writing is that different things combined
> > together should visually
> > fall-apart - they should be easily decomposable into components.
> >
> > Since function type / array type combinations are deprecated anyway, this
> > proposal steps right
> > onto the syntax tokens that are traditionally reserved for arrays. It
> does
> > not prevent
> > combinations of function types and array types but it makes the less used
> > combination more
> > awkward-looking to benefit other more useful combinations (like casting
> to
> > function types,
> > specifying function-typed parameters in methods, chaining method and
> > function calls).
> >
> > The syntax of expression lambda is similar to parenthesized expression.
> It
> > just adds optional
> > formal parameters and a mandatory delimiter immediately after opening
> '('.
> > Likewise the syntax
> > of statement lambda is similar to block statement. It just adds optional
> > formal parameters and a
> > mandatory delimiter immediately after opening '{':
> >
> > (12) vs. (:12)
> >
> > { System.out.println(); } vs . {: System.out.println(); }
> >
> >
> > Regards, Peter
> >
> >
>
>
More information about the lambda-dev
mailing list