Project Lambda: Java Language Specification draft 0.1.5
Paul Benedict
pbenedict at apache.org
Sat Feb 13 06:25:43 PST 2010
What happened to the self.invoke() syntax? A barrage of people came
out saying self.() looks like a syntax error (I agree); I don't recall
anyone advocating the syntax after the first draft was released.
On Fri, Feb 12, 2010 at 9:04 PM, Neal Gafter <neal at gafter.com> wrote:
> A few flubs and omissions that I noticed:
>
> - Your grammar is ambiguous. Expression goes to both LambdaExpression
> and (indirectly) to Primary, both of which have a way of writing a
> lambda.
>
> - It is unclear what the type of "this" is in an expression lambda. Is
> it forbidden?
>
> - I wonder if the identity of a lambda can change spuriously. For
> example, if "this" refers to the lambda expression, can it be expected
> to have the same value on each invocation of the same lambda
> expression? In other words,
>
> #Object() self = #()this;
> assert self.() == self.(); // guaranteed??
>
> - Similar question if the lambda has been converted to a SAM
>
> Object() self1 = #()this;
> Callable<Object> self2 = self1;
> assert self1.() == self2.call(); // guaranteed??
>
> - What is the meaning of "toString()" inside a lambda? Does it refer
> to the method inherited by the lambda from Object, or from the
> enclosing scope?
>
> - It isn't clear why you would want special rules for recursive
> lambdas in this revision of the spec, given that one could just invoke
> "this" inside the lambda. Or, failing that, just use a method or an
> anonymous inner class.
>
> - In your example where there is an "unreachable return statement",
> the return statement is (formally) reachable. Any unreachable return
> statement would be a compile-time error because it is an error to have
> an unreachable statement in Java.
>
> - Your definition of effectively final mentions "target of an
> initialization", but that doesn't make sense. It can only be the
> target of an initialization in its declaration, and it is always
> definitely unassigned before then. (Yes, even local variables in
> switch statements)
>
> - The spec "It is a compile-time error to modify the value of an
> effectively-final variable in the body of a lambda expression." is
> meaningless. If there were an assignment to a variable from an
> enclosing scope in a lambda, the variable would not be definitely
> unassigned at that point, and so by definition the variable would not
> be effectively-final. So this rule could never be applied in the way
> you appear to intend. The only way the rule could be applied is
> definitely something you do not want to forbid:
>
> Object o = #(){
> int x; // x is effectively final
> x = 3; /* error: It is a compile-time error to modify the value of
> an effectively-final variable in the body of a lambda expression */
> };
>
> - Your example "The constraint #int(String) >> #int(T) resolves to
> String>>T" in incorrect. It resolves to T>>String.
>
> - Your inference algorithm doesn't allow the use of the lambda
> conversion. Specifically, if you try to pass
> #()("Foo")
> to a method
> <T>void f(Callable<T>);
> there is no way to infer that T=String.
>
> - Your assignment conversion doesn't allow a subtype conversion
> followed by a lambda conversion. Consequently, you may force
> programmers to use temporary variables just to force the compiler to
> do a subtype conversion before the lambda conversion. In expression
> contexts (i.e. super() invocations) that is cumbersome indeed.
>
> - Your rules for lambda conversion appear to improperly erase some
> types. For example, the following code is ruled illegal
>
> interface Receiver<T> { void f(T); }
> Receiver<List<String>> rls = #(List<String> ls)(); // error:
> "List<String>" is not the same as "List".
>
> - The specification for a SAM type says that "If a SAM type is a class
> type, then it must be declared abstract and have an accessible no-args
> constructor.". That makes the following (currently legal code)
> illegal:
>
> abstract class SAM { private SAM(int arg){} abstract void f(); } //
> error: SAM type does not have no-args constructor
>
> - There are no accessibility constraints on the methods of a SAM.
> What if the abstract method is package-private to someone else's
> package? Or, what if there are two override-equivalent abstract
> methods that are package-private to different packages? Generating
> correct code for (a lambda conversion in) this case is extremely
> cumbersome, and may require generating three or more classes in
> different packages.
>
> - The following is a SAM (it has only one non-generic abstract
> method), but should not be considered a SAM
>
> interface SAM { void foo(); <T> void bar(int x); }
>
> - Your specification [11.2.2] makes no sense. You have the exceptions
> from the body of a statement lambda being thrown where the lambda
> expression appears. A lambda expression should throw no checked
> exceptions.
>
> - You don't describe the cases in which a lambda conversion can throw
> a checked exception. For example, what if the SAM constructor declared
> an exception?
>
> - Your handling of exceptions in the lambda conversion is not correct.
> For example
>
> interface I1 { void f() throws X1; }
> interface I2 { void f() throws X2; }
> interface I3 : I1, I2 {}
>
> I3 x = #(){ throw new X1(); } // allowed, even though I2.f() doesn't throw X1.
>
> - You say "let M be the set of methods..." but you mean "let S be the
> set of abstract methods...".
>
> Cheers,
> Neal
>
>
More information about the lambda-dev
mailing list