# considered harmful [was C++11 lambdas]

Reinier Zwitserloot reinier at zwitserloot.com
Mon Mar 15 21:55:45 PDT 2010


So, postfix dots are bad, but when your favourite proposal ends up being
ambiguous, it's okay to add double prefix dots. Hm. Doesn't seem fair.

It's just not that simple. Shadowing a field with a local variable
declaration is, well, local. It occurs within the method itself. For closure
invoke vs. method invoke this granularity level all of a sudden becomes the
class.

It doesn't really make the no-dot proposal any simpler than the dot
proposal, and you haven't addressed any of the other concerns (closure
invokes are a different concept compared to method invokes, and a visual cue
is nice).


It's insulting when nobody agrees with closures mean? The folks that are
actually writing the proposal seem to agree. It also seems a bit odd to hold
lambda-dev responsible for the fact that the 'closure' term has been watered
down so much due to usage that goes back many years, well before lambda-dev
was set up.

You seem to be mistaken about how the status quo proposal closes around
local variables. It does close around *ALL* of them. The one difference with
most other languages is that the compiler, while it fully understands what
you meant, refuses to compile it until you tell the compiler that you really
did intend for the compiler to declare that variable on the heap, accept
that thread synchronization issues can now crop up, and other such issues.

This, too, has been covered, at length. The JVM memory model cannot be
adapted to let closures access and mutate local variables of their outer
scope trivially, and not even after some thought, so without some
breakthrough proposal to show how this is doable this remains off the table.
Which leaves the compiler generating a bunch of sugar to make it happen.

Does this mean "volatile" can be put on any local variable, or only on local
variables that are secretly heap-hosted? Does this mean that heap-hosted
local variables are initialized to null/false/0 the way fields are, or is
all usage in closures restricted to require definitive assignment prior to
the closure even being defined, with a further restriction that no closure
can set a final unset local?

You're also going to create surprise code:

Runnable[] runnables = new Runnable[3];
for (int i = 0; i < 3; i++) runnables[i] = #() {System.out.print(i);};
for (int i = 0; i < 3; i++) runnables[i].run();

This will print "333" in your proposal - quite the surprise. It'll not
compile in the status quo as the closure is accessing mutated local
variables. How do you suggest this is handled? Let it pass and decide that
the masses that are going to stumble on this will just have to become
smarter, and perhaps tell Oracle to hire a dedicated guy to respond to the
avalance of reports at bugs.sun.com? Perhaps an exemption should be made for
local variables declared in a basic for's init, and we should say _those_
variables cannot be closed over to avoid this problem. But then the proposal
isn't as simple and straightforward as you seem to think, and it would help
a great deal if you could produce a thorough list of exactly how your
proposal works that includes such corner cases.

NB: I take it you're aware that the status quo proposal allows closures to
access *final* locals, just like this is legal in Anonymous Inner Classes in
today's java? It's also (IIRC) on the fence leaning towards allowing access
to effectively final locals (locals that aren't marked final but are
nevertheless set exactly once, and this set occurs before the closure is
defined) by treating the local declaration as implicitly final. You're
getting awfully worked up about postfix dot and the need to mark *mutated*
local variable declarations that are accessed in a closure, given that for
both of those, there's no simple answer.

--Reinier Zwitserloot



On Tue, Mar 16, 2010 at 3:07 AM, Bob Foster <bobfoster at gmail.com> wrote:

> On Mon, Mar 15, 2010 at 4:33 PM, Reinier Zwitserloot
> <reinier at zwitserloot.com> wrote:
> > Do you have *ANY* comments at all about the many many problems that this
> > mailing list uncovered with your 'preferences', or are you just whining?
>
> One person's opinions are another's whining, whatever. I have a day
> job, so I get the digest and don't follow this list moment by moment.
> If someone copies me, I reply.
>
> I've already apologized for coming late to the party. Once is enough.
>
> > A small and incomplete rehash:
> > 1. No '.'
> > Java has an almost unique take on namespaces, in that in java types,
> methods
> > and variables all have their own namespace. Without that dot, the meaning
> of
> > "foo()" is ambiguous. Are you invoking the method named 'foo', or are you
> > invoking the closure pointed at by variable foo?
>
> Agreed that within a class a reference to a method and a call through
> a variable of function type with the same number and type of arguments
> would be ambiguous. Using . as a prefix operator for indirect function
> calls with that issue is as good a device as any. You still have a
> problem with references to static function variables within a class
> and references outside the class, unless the proposal is to double up
> the dots, like:
>
> A..foo()
> a..foo()
>
> Regardless, such notation should be required _only_ if the call would
> be actually ambiguous, a fairly minor use case. Inside a class, a
> field name is not required to be qualified by 'this' unless necessary
> to disambiguate the reference; a static method name is not required to
> be qualified by the class name unless necessary to disambiguate from a
> non-static method. This should be treated the same.
>
> The example I was looking at, however, involved only function type
> arguments, and I see no reason to saddle references to argument names
> or local variables with gratuitous dots. As long as "inner functions"
> can only be defined through variables, there is no namespace issue and
> the scope rules handle the rest.
>
> > The primary proposal
> > started out without that dot, as per the strawman. In other words, we
> > covered this. At extreme length. There's no point re-raising this issue
> > unless you come up with different solutions for the namespace issues.
> IIRC,
> > the dot has going for it:
> >  - No need for arbitrary ordering of namespaces in case foo is both a
> method
> > and a variable.
> >  - Closures in java are to a smallish extent shoehorned in. They are
> unique
> > things that aren't exactly like methods, so their invocation should look
> a
> > little different.
> > These advantages were deemed superior to the advantage that dotless
> > invocation has, which one dot less clutter at the cost of syntax
> ambiguity.
>
> Ah, deemed.
>
> > 2. "Actual closures"
> > The word 'closures' is pretty meaningless. It has a well defined term in
> the
> > academic sense, and, frankly, its definition is pretty well defined in
> the
> > dictionary sense too, *but*, the vast majority of java programmers have
> been
> > abusing the term to mean something different. At any rate, whining about
> > "actual closures" misses the point completely. Project Lambda's aim is to
> > create syntax that makes it easy to write a bunch of code that's bundled
> up
> > into a reference so that you need not execute it on the spot, but can
> > instead hand it off to for example another method, with as primary use
> case
> > extra-jsr166y a.k.a. ParallelArrays. From the outset (the outset being
> Mark
> > Reinhold's strawman at Devoxx '09) Project Lambda did not aim to add
> > concepts like keeping control statements such as 'break', 'continue' and
> > 'return' transparent. The aims of Project Lambda have not changed since
> its
> > inception. Possibly you were just confused as to what they were.
>
> I agree it's pretty meaningless in this forum, and I wish you would
> stop referring to functions as closures. If nobody agrees what a
> closure is, it's insulting.
>
> If you care, though, I mean closures as they are meant, according to
> Wikipedia, in computer science: "a closure is a first-class function
> with free variables that are bound in the lexical environment." When I
> say that the proposal doesn't do real closures what I mean is it does
> lexically closed named constants. Better than nothing but a bit
> tedious to work around by hand.
>
> (Even considering break, etc. must mean someone confuses closures with
> Smalltalk blocks and their spawn.)
>
> Bob
>
> >
> >
> > On Mon, Mar 15, 2010 at 11:57 PM, Rémi Forax <forax at univ-mlv.fr> wrote:
> >>
> >> Le 15/03/2010 23:27, Bob Foster a écrit :
> >> > Harmful because it's unpleasant to look at and leads to indecipherable
> >> > code. Every time someone proposes adding another #, the syntax gets
> >> > uglier and less readable.
> >> >
> >> > I apologize for coming to this point rather late, but frankly once I
> >> > read the # proposal and realized no one intended to implement actual
> >> > closures, I decided the whole project was a plot to convert Java
> >> > programmers to Scala and my mind turned to more pleasant things. This
> >> > was a mistake, and Remi Forax's excellent counter-proposal has
> >> > inspired me. Why _not_ try something simpler?
> >> >
> >>
> >> Yes, a supporter.
> >>
> >> > I have a (very) few nits to pick with Remi's proposal:
> >> >
> >> > - int(int) is a function type, not a function.
> >> >
> >> > - the . has no place in function call syntax; functions are not
> methods.
> >> >
> >>
> >> It will be cool to be able to call a function only by its name
> >> but it doesn't seem possible to twist the JLS invocation rules
> >> to do that (see the archive of this list for more info).
> >>
> >> > - I quite like the ( expr ) syntax when a function body is only a
> >> > single expression, but it's not essential and if it were adopted
> >> > should be extended to methods for consistency.
> >> >
> >> > - Java doesn't have type inference elsewhere, so it seems inconsistent
> >> > to have it for functions. However, if it was going to be part of the #
> >> > syntax, it should be allowed here, too, as Remi originally proposed,
> >> > and extended to methods, as well.
> >> >
> >>
> >> Java has type inference when resolving generic method calls and
> >> when using the diamond operator.
> >>
> >> > The whole proposal works syntactically because currently the
> >> > construction Type() never appears in a valid program except after new.
> >> > So as long as new doesn't pollute anonymous functions (a separate
> >> > thread), function types are unambiguous to both the compiler and
> >> > readers.
> >> >
> >>
> >> [...]
> >>
> >> Rémi
> >>
> >
> >
>


More information about the lambda-dev mailing list