Too terse and too alien?

Alessio Stalla alessiostalla at gmail.com
Tue Jun 1 12:35:58 PDT 2010


On Tue, Jun 1, 2010 at 8:54 PM, Mikael Grev <grev at miginfocom.com> wrote:
> Thanks Ruben, I feel the exact same way and has been going on and off if I was to say something given that almost all on this list seem to be very compiler focused, at least those who respond.
>
> What won't be understood by the general (95%) developer is the reasons why syntax turned ugly/non-Java/whatever. They will all judge closures by the simplicity of the syntax, how "Java-like" it is, and do so swiftly with a few examples. And mind you, Java-like will mean different things to different people, which makes this all so complex.
>
> As I think Oracle already know, things like
>
>  myClosure.(1, 5)
>
> won't fly very well with the general developer. The reasoning behind the dot, that the name otherwise lives in the same name space as methods, is not understandable by most. And even for me it looks like a compiler purists way of reasoning. myClosure(1, 5) is the only way. It looks Java (my interpretation if it) and my IDE will color/font code it for me to distinguish it from a method call, which it isn't completely unrelated to anyway.

I don't like .(...) either, but saying that myClosure(1, 5) is the
only way is a bit simplistic imho. This substantially affects an
important aspect of the language, that is, how symbols are resolved to
program constructs. So far in Java foo() is only legal if foo is a
method, while foo.bar is only legal if foo is a variable or a field.
By choosing to (or not to) invoke closures like methods, you're making
a trade-off between uniformity - everything that can be called is
called like foo() - and separation of namespaces - you can't
accidentally shadow a method with a variable (or a field!) or
vice-versa, depending on how precedence between the two is specified:
is foo.bar() a call to method bar() or a call to the closure stored in
the field named bar?

If I'm allowed to divert a bit to non-Java folklore, this issue
resembles very closely what in the Lisp world is known as Lisp-1 vs
Lisp-2, i.e., one namespace for functions and variables vs two
separate namespaces. The first makes functional programming more
convenient (there's no need of an explicit operator to call a closure,
like the dot in this case), the latter makes name clashes much rarer
and so, for example, makes it safer to write macros (i.e., code
transformations - making a parallel with Java, you could say that it
makes refactoring less problematic, for example). People are very
passionate about this issue even today, many years later than it was
first raised, so I wouldn't dismiss it as a problem for compiler
purists only.

> I also believe that
>
>   myMethod(Runnable r)
>
> should be invoked
>
>   myMethod( #{System.out.pringln("") } );
>
> and that the parsing should be lenient with all the missing parenthesis and semi colon stuff, if at all possible without creating ambiguities. Same there, I understand the reasoning why someone wants to keep the parsing clean but, again, that is the parser coder's problem and I would happily give the extra resources for it if I were at Oracle. All in the very important name of shaping how this will be received in the blogosphere.
>

I agree to a certain extent, but keep in mind that complicating the
parser too much has a negative effect not only on the parser itself,
but on all the tools that parse Java code, including IDEs, so it's
again a matter of trade-offs.

> Also,
>
> #(int i) (i * i)
>
> should be written
>
> #(int i) {i * i}
>
> just like a normal closure. There's no need to make it special and use parenthesis just because it is only one expression in there. That's for the parser/compiler to figure out. Less to learn, easier for the user. And he can write it
>
> #(int i) {return i * i}
>  or even
> #(int i) {return i * i;}
>
> without making it look like something else entirely.

I agree to having only a single syntax, #(int i) {return i * i;}. An
extra return won't make much difference, and special-casing closures
with a single expression as their body makes it slightly inconvenient
to change them in case you later need to have more than an expression.
Consider also that Java is not a functional language, and its
expressions are limited to math, assignments, comparisons, and ternary
conditionals; if, try-catch, switch, etc. are not expressions, so I
think single-expression closures will be seldom used anyway.

>
> I don't in any way say that the syntax simplifications above is the ultimate answer, or even better. But anyone that don't understand why those kind of user-space simplifications are important shouldn't have a final call on the syntax IMO.
>
> KISS, and let the compiler/parser do the heavy lifting.
>
> Cheers,
> Mikael
>

Cheers,
Alessio


More information about the lambda-dev mailing list