Bitten by the lambda parameter name

Peter Levart peter.levart at gmail.com
Fri Jul 19 14:42:26 PDT 2013


On 07/17/2013 11:37 AM, Remi Forax wrote:
> On 07/17/2013 11:28 AM, Maurizio Cimadamore wrote:
>> On 17/07/13 09:48, Remi Forax wrote:
>>> On 07/17/2013 01:29 AM, Zhong Yu wrote:
>>>> It creates a dilemma for API designers. In this case Doug Lea chooses
>>>> efficiency, at the cost of annoying user Remi Forax.
>>>>
>>>> Programmers would love to reuse simple names. Here's an example that
>>>> seems pretty reasonable, note the two "event" variables
>>>>
>>>> buttonA.onClick(event->{
>>>>        ...
>>>>        buttonB.enable();
>>>>        buttonB.onClick(event->{ form.submit(); })
>>>> });
>>>>
>>>> Zhong Yu
>>> yes, this one is a also good example of why a lambda parameter should
>>> hide a local variable.
>> Except, here there's no local variable hiding - you have two nested
>> lambdas, where the parameter of one hides the parameter of the other.
>> If you wrote a rule specifically targeting this example, you would
>> soon find out that you'll still be stuck with your original
>> computeIfAbsent example.
>>
>> Maurizio
> I use 'local variable' as a broader term, for parameter, real local
> variable, exception parameter, etc.
>
> Rémi

Yes, and the rule currently says that a 'local variable' (even if in 
nested scope) can not shadow a 'local variable'. But we could argue that 
a local variable declared outside lambda body, if referred to from 
within lambda body, becomes some kind of final field as far as it's 
lifetime is concerned - tied to the lifetime of lambda-as-object. And 
local variables can shadow fields...

I guess it's a matter of how strict the lambda transparency is respected...

Regards, Peter

>>> Rémi
>>>
>>>> On Tue, Jul 16, 2013 at 3:20 PM, Dan Smith <daniel.smith at oracle.com>
>>>> wrote:
>>>>> On Jul 16, 2013, at 9:20 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>>>>>
>>>>>> On 07/16/2013 05:05 PM, Maurizio Cimadamore wrote:
>>>>>>> On 16/07/13 16:00, Peter Levart wrote:
>>>>>>>> Perhaps here, an overloaded Map.computeIfAbsent that takes a
>>>>>>>> Supplier
>>>>>>>> instead of Function would be handy. Even when you need the key to
>>>>>>>> construct new value, it is usually ready in some effectively-final
>>>>>>>> variable in the scope. And when you don't need the key, a
>>>>>>>> constructor
>>>>>>>> reference could be applied like:
>>>>>>>>
>>>>>>>> partySetMap.computeIfAbsent(kind, HashSet::new).add(...);
>>>>>>> +1
>>>>>>>
>>>>>>> I think the underlying problem to this discussion might be that
>>>>>>> there
>>>>>>> are places (and computeIfAbsent seems to be one of them) where the
>>>>>>> lambdi-fication of the library took a somewhat convoluted path, in
>>>>>>> which the 'same' variables needs to be supplied multiple times in
>>>>>>> order to keep the chain happy (which then turns out to be
>>>>>>> problematic
>>>>>>> because of scoping rules).
>>>>>> There is a big difference, if you provide the key as parameter the
>>>>>> lambda will be a constant so the cost of using it is 0
>>>>>> (if you forget the initialization cost), if you don't provide the
>>>>>> key as
>>>>>> parameter, you will need to capture it and in that case, the runtime
>>>>>> will create a fresh lambda for each call.
>>>>> So this amounts to a language feature request to facilitate a
>>>>> performance optimization.  You'd like to avoid capture by using a
>>>>> pattern that relies on re-declaring variables for identical values,
>>>>> because capture is less efficient.  Thus, you wish the language
>>>>> were more friendly to re-declarations.
>>>>>
>>>>> In such situations, it's appropriate to ask: is this the tail
>>>>> wagging the dog?  Capture is the _right_ way to express what's
>>>>> going on, even if it's less performant.  Right?
>>>>>
>>>>> I wonder if the efficiency problem will be optimized away someday.
>>>>> Maybe with value types, the VM could avoid boxing up the capture
>>>>> variables with the underlying function?
>>>>>
>>>>> —Dan
>>>>>
>>>>>



More information about the lambda-dev mailing list