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.
A+
Osvaldo
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