Primitives in Generics (+ the meaning of this)

Peter Levart peter.levart at marand.si
Fri Jul 16 11:17:00 PDT 2010


On 07/16/10, Joshua Bloch wrote:
> Peter,
> 
> On Fri, Jul 16, 2010 at 8:28 AM, Peter Levart <peter.levart at marand.si>wrote:
> 
> >
> >
> > Regardless of that, do you aggree that the statistical evidence, prepared
> > by some members of this list, showed that usage of explicit and implicit
> > "this" inside anonymous inner SAM subclass creation expressions is
> > practically non-existent and is actualy "in the way" of using outer.this
> > and/or outer instance members (even a cause of bugs in JDK itself)?
> >
> 
> I don't remember the details of the statistical evidence, but it seems
> suspect. 

I aggree that the sample of sources should be much greater to have any statistical meaning. I remember that not much more than 4 or so projects were scanned (OpenJDK and IntelliJ IDEA among the bigger ones) and not all of them used consistent methodology. It was only an illustrative attempt but one which indicated that the usages of outer instance members and/or outer.this might be much more frequent than usages of inner this and/or inner instance members. So what is stopping us from doing a more complete analysis as the next step?

> It's not uncommon for periodic TimerTasks to cancel themselves or
> (as illustrated in the TimerTask documentation) to call their own
> scheduledExecutionTime()method from their single abstract method (run). It
> may be the case that it's much more common to want to access enclosing
> instances, but I don't believe that intentional access to the function
> object from within its body is "practically non-existent."

There absolutely should be an acceptable, elegant and consistent way to intentionally access the members of the target SAM instance from within the lambda body. There were already long discussions about alternatives to "this" on this list. None of them seems to be liked by deciding factors so the latest specification uses "this" for that purpose. But do you aggree that if non-disputable statistics showed that usages of "this" referring to target SAM instance are greatly outnumbered by usages of outer.this, wouldn't it be right to consider a more awkward alternative for accessing target SAM instance and use "this" to refer to lexically surrounding instance (and do the same with unqualified members)?

Does that depend on how awkward the alternative might be?

Ok, here's another attempt:

> 
> Josh
> 
> P.S. It took me ten seconds of searching to find this example:
> www.google.com/codesearch/p?hl=en#xJfZyRTTR4E/trunk/src/com/bwepow/wwj/awt/KeyPollTimer.java&q=TimerTask%20scheduledExecutionTime&sa=N&cd=27&ct=rc&l=118
> 

Taking the above example and pasting relevant lines here:


    public synchronized void start()
    {
        if (this.timerTask == null)
        {
            this.timerTask = new java.util.TimerTask()
            {
                public void run()
                {
                    long time = System.currentTimeMillis();
                    if (time - this.scheduledExecutionTime() >= 2 * KeyPollTimer.this.period)
                        return;
                    KeyPollTimer.this.updateAndNotify(KeyPollTimer.this.listener);
                }
            };
            if (this.timer == null)
                this.timer = new java.util.Timer();

            this.timer.schedule(timerTask, 0, this.period);
        }
    }


would be rewritten to use lambda expression like this:


    public synchronized void start()
    {
        if (this.timerTask == null)
        {
            this.timerTask = { ->
                    long time = System.currentTimeMillis();
                    if (time - this.scheduledExecutionTime() >= 2 * KeyPollTimer.this.period)
                        return;
                    KeyPollTimer.this.updateAndNotify(KeyPollTimer.this.listener);
                };
        
            if (this.timer == null)
                this.timer = new java.util.Timer();

            this.timer.schedule(timerTask, 0, this.period);
        }
    }


alternative way to refer to target SAM instance might be:


    public synchronized void start()
    {
        if (this.timerTask == null)
        {
            this.timerTask = {task: ->
                    long time = System.currentTimeMillis();
                    if (time - task.scheduledExecutionTime() >= 2 * KeyPollTimer.this.period)
                        return;
                    KeyPollTimer.this.updateAndNotify(KeyPollTimer.this.listener);
                };
        
            if (this.timer == null)
                this.timer = new java.util.Timer();

            this.timer.schedule(timerTask, 0, this.period);
        }
    }


The optional "self" parameter is the first parameter in the list and delimited with ':' from other function parameters. With target typing it doesn't take to much space. Is this too awkward and unintuitive?

This alternative has one advantage to "this". If you want to refer to an "outer" lambda instance from within a nested lambda expression body, currently you could do that only by assigning "this" to a local final variable:


final Executor executor = ...;

Runnable r = {->
  final Runnable outer = this;
  executor.execute({-> executor.execute(outer); });
};


With alternative approach this is a one-liner:


Runnable r = {outer: -> executor.execute({-> executor.execute(outer); }); };


I know that such usages might be even less frequent than referrals to inner SAM instance from the lambda body, so this is not an issue - just illustration.

But in the future, such optional syntax addition could also be used as the target name of the long return for example:


final List<String> strings = ...;

Callable<String> fistLambda = {outer: ->
  strings.forEach({s -> if (s.startsWith("lambda")) return outer : s; });
  return null;
};


Regards, Peter


More information about the lambda-dev mailing list