m.invoke() vs. m() vs. m#()

Osvaldo Pinali Doederlein opinali at gmail.com
Sun Dec 13 07:38:59 PST 2009

Well put Vladimir. You remember me the eighties when we had those 
primitive BASIC languages, often with different suffixes for each data 
type - A$ for a string variable, A% for integer, A# for float or 
something like that - because type-unambiguous variable references 
allowed a simpler interpreter and typechecker. (I presume many 
programmers though that to be more readable to... so they 
invented/abused idioms like Hungarian notation years later.)

Java already allows for ambiguity in many important places; as we're 
discussing closures, I could mention existing method invocation - as we 
have polymorphism, which is ALL ABOUT introducting ambiguity, and that's 
a core tenet of OO! Where some people see ambiguity, others see 
simplicity and expressiveness. We could even talk about cleaning up some 
of the existing syntax... for example, why Java needs separate 
'extends'/'implements' keywords? The separate 'class'/'interface' 
keywords are sufficient to make these concepts clearly separated; the 
extra 'extends'/'implements' redundancy is a clear violation of DRY. 
[This is just rhetorics; I'm not seriously suggesting to deprecate 
'implements' (or both keywords - in favor of something neutral like 
C++'s ':').]

OTOH, not all language changes that add ambiguity should be accepted, 
even if they demonstrably make the language more powerful. For one 
thing, dynamic typing is not in my wish list for Java, because Java is a 
static typed language and I like it that way; it's a fundamental part of 
the language's core values and paradigm. Dynamic typing carries 
significant tradeoffs in performance and remarkably compile-time 
checking; if I wanted a "dynamic language" I'd run to Groovy, JRuby, 
Clojure etc.

In summary, ambiguity is a HIGHLY overrated issue. I cannot imagine any 
single programming language trait that produces more ambiguity than 
dynamic typing, remarkably with powerful MOPs; still, half of the world 
likes to program that way because (IMHO) they equate productivity & 
readability to "less lines of code" and in that case it's hard to beat a 
dynamic+meta language.

But closures extend the current language design naturally - in fact, 
closures _fixes_ this design (<gasp> inner classes <gasp>). The only 
real issue is: would transparent closure invocations (sans .invoke or 
any custom syntax) make the language _significantly_ more complex, in a 
way that matters to _end users_? Previous language enhancements - 
generics, autoboxing and varargs - have accreted much more complexity in 
this area than closures could possibly do. In fact, from my (admittedly 
non-expert) reading of the JLS, I'd say ANY of those changes alone 
create more drama than closures would.

Quick puzzler: if you have f(int,Double) and f(Integer,double...), which 
method is invoked by f(0,1)? A common programmer who's never read the 
JLS would likely expect the compiler to prefer f(int,Double) that only 
requires autoboxing 1; but the right answer is f(Integer,double...), 
requiring both autoboxing 0 and wrapping 1 in a single-element double[]. 
If the "old-style" resolution fails, the JLS says to try again with 
autoboxing but without varargs; only in a third step varargs are 
considered. The rationale is to privilege fixed arity, but this is not 
obvious/intuitive, I just demonstrated that it doesn't always result in 
the simpler invocation (requiring less parameters to be wrapped). This 
rule is arbitrary enough to be at least as bad as anything transparent 
closure calls could bring (as far as I can see - I could be wrong). Yet, 
I use varargs as much as I can, and never found the ambiguity to be an 
issue in the real world.


Em 13/12/2009 09:25, Vladimir Kirichenko escreveu:
> Peter Levart wrote:
>> This has the benefit of:
>> - being unambiguous (no need for special shadowing/name-space rules)
> Why be unambiguous here? For what? Just to have ability to name
> everything with the same name?
> Why don't we have special syntax for making unambiguous:
> * interfaces: class X interface %X
> * enums: class X{} enum $X{};
> * constructors (why not?): class X { ~X(){} }
> * final fields/variables: public static final String&CONST;
> * static methods:  C.*m*();
> * !this()
> * ^super()
> Every of above examples could be supported with every argument against
> ambiguity shown here. Why don't we have it?  And having this things
> ambiguous we seem not have any problems with "ambiguity".
> Closure is a function. It's a natural to call function, any
> function(constructor, static method, this(), super()) without pointing
> out with verb "call it" or hieroglyph defining the same.

More information about the closures-dev mailing list