JSR 335 Lambda Specification, 0.9.0
daniel.smith at oracle.com
Mon Jan 13 16:00:42 PST 2014
Responses to some comments received at lambda-spec-comments:
On Dec 30, 2013, at 4:24 AM, v.a.ammodytes at googlemail.com wrote:
> In Part B, 14.18 (The throw Statement), the appearance of 'in a method declaration' was extended to 'in a method declaration or a lambda expression'. The whole sentence now reads:
> If a throw statement is contained in a method declaration or a lambda expression, but its value is not caught by some try statement that contains it, then the invocation of the method completes abruptly because of the throw.
> Maybe this is nit-picking, but I'm missing a similar extension of the second half of this rule, because the invocation of a lambda is not the same as the invocation of a method.
On the contrary, invocation of a lambda is _only_ via invocation of a method -- there is no other invocation mechanism. (I recognize that the wording in this sentence is subtle, but I didn't want to make a big deal about lambda expressions here by adding a lot of clarifying text.)
> In Part G, 18.2.3 (Subtyping Constraints), the algorithm to reduce ⟨S <: T⟩ where none of the first four cases applies starts with:
> If T is a parameterized class or interface type, or an inner class type of a parameterized class or interface type (directly or indirectly), let A1, ..., An be the type arguments appearing in T; among the supertypes (4.10) of S, a corresponding class or interface type is identified, with type arguments B1, ..., Bn. If no such type exists, the constraint reduces to false. Otherwise, the constraint reduces to the following new constraints: for all i, 1 ≤ i ≤ n, ⟨Bi <= Ai⟩.
> This leaves open the question, what shall happen if there exists more than one suitable candidate among the supertypes and the arbitrarily chosen candidate happens to reduce to false later on.
> After digging into some more of part G and following the link to the work of of Kennedy and Pierce in the comments to 18.3, my best guess would be that the intended algorithm in 18.2.3 is meant to backtrack and try out all candidates one at a time. Am I guessing correctly? If so, I propose to be more specific about this, either in the spec or in a comment.
The definition of "supertypes" in Chapter 4 is somewhat vague -- that's something I'd like to clean up in the future -- but the idea is that it is a finite set and never includes two parameterizations of the same class. The well-formedness rules for class declarations (8.1.5) and type parameter bounds (4.4) help to guarantee this property.
So, no, there's no need (or support) for backtracking -- we pursue the only possible path.
> In Part C, 15.28 (Method Reference Expressions), one of the provided examples may require updating:
> (test ? list.map(String::length) : Collections.emptyList())::iterator
> In an earlier version of the API, the List interface probably contained a map method returning a new List. Readers unaware of this history may be puzzled by this example.. An updated version may look like this:
> (test ? list.stream().map(String::length).collect(Collectors.toList()) : Collections.<Integer>emptyList())::iterator
Agreed this should be fixed. No need for semantic equivalence, though -- it's just an illustration of syntax. Here's my fix:
(test ? stream.map(String::trim) : stream)::toArray
> BTW: The type parameter on Collections.emptyList is annoying, but without it b120 fails to compile this code fragment.
Correct. Addressed by just getting rid of it entirely.
More information about the lambda-spec-experts