Preparing for the 0.2 draft

Mark Mahieu markmahieu at googlemail.com
Thu Feb 4 14:26:28 PST 2010


On 4 Feb 2010, at 21:08, Joshua Bloch wrote:

> Mark,
> 
> On Thu, Feb 4, 2010 at 12:27 PM, Mark Mahieu <markmahieu at googlemail.com> wrote:
> 
> On 4 Feb 2010, at 05:56, Joshua Bloch wrote:
> 
> > Neal found 48 locations in OpenJDK 6 in which he claimed that evaluating
> > "this" in the surrounding context would be helpful. I decided to take a
> > closer look at them in hopes of learning something.
> 
> <snip>
> 
> > 4 could not take advantage of the
> > "enclosing scope semantics for this," because the anonymous class has a
> > method that shadows the one in the enclosing class (see (1) below for an
> > example)
> 
> If "this" were evaluated in the context of the enclosing class, how could shadowing come into play here?  Wouldn't the former preclude the latter?
> 
> This class of uses concern SAM types, exclusively. Technically you're right. But evaluating "this" in the enclosing context of a "SAM lambda" is a bit harder to fathom. If you're implementing the compare method of a Comparator instance and you invoke the compare method, you probably expect a recursive invocation.
>  
> 
> > (1) src/share/classes/com/sun/java/util/jar/pack/Histogram.java:187
> >
> > class Histogram {
> >    public double getBitLength(int value) {
> >        double prob = (double) getFrequency(value) / getTotalWeight();
> >        return - Math.log(prob) / log2;
> >    }
> >
> >    private final BitMetric bitMetric = new BitMetric() {
> >        public double getBitLength(int value) {
> >            return Histogram.this.getBitLength(value);
> >        }
> >    };
> > }
> >
> > The qualified this is necessary only because the anonymous class gives its
> > sole method the same name as the one that it wants to call in its enclosing
> > instance. But you can't name the method in a lambda expression, so having
> > "this" evaluated in the surrounding context would not be necessary (or
> > helpful) here.
> 
> The method is named anyway, by the BitMetric interface.  Surely it's whether or not that is visible in the body of an equivalent lambda which determines how helpful a given approach is?  For this particular example, the "evaluated in surrounding context" approach works out the same as the approach in the v0.1 draft spec, I think.  Or is that your point?
> 
> I was purpose vague in discussing "class 4." I do believe the examples in this class don't benefit from evaluating this in the surrounding context, but it's hard to discuss them precisely until we firm up our story on SAM types.
> 
>         Josh
> 
> P.S.  Also I reviewed 48 (!) uses, which limited the amount of time I could spend thinking about each one.
> 

Ok, no criticism was intended, I just thought I was having a reading comprehension failure or something.  Thanks for taking the time to expand on your original comments.

Actually, that particular example grabbed my eye because I've noticed a number of similar cases in the last few days, but where a class has been written almost as it would if it directly implemented some interface, but the programmer has wanted to keep that an implementation detail so used an intermediary anonymous inner class which forwards to a (normally private) method on the containing class:

	interface Listener { void onEvent(Event e); }

	class Foo {
		...
		bar.addListener(new Listener() {
			public void onEvent(Event e) {
				Foo.this.onEvent(e);
			}});
		...

		private void onEvent(Event e) {
			// important code
		}
	}

Just as is the case with your Comparator example (and the Histogram code), I certainly agree that it's interesting to consider what the author would expect if they were to write something like:

		bar.addListener(#(Event e) { onEvent(e); });

But equally interesting is what someone else would make of it when reading that code at a later point, especially since the only obvious onEvent method present is on the containing class.

Regards,

Mark







More information about the lambda-dev mailing list