Why don't lazy parameters bind to delegates? Was: Feature to get or add value to an associative array.

Steven Schveighoffer schveiguy at yahoo.com
Fri Apr 20 23:36:57 UTC 2018


On 4/20/18 5:40 PM, Jonathan M Davis wrote:
> On Friday, April 20, 2018 16:35:43 Steven Schveighoffer via Digitalmars-d
> wrote:
>> On 4/17/18 4:49 PM, Steven Schveighoffer wrote:
>>> On 4/17/18 12:18 PM, Nick Treleaven wrote:
>>>> Thanks for making this pull, I've thought about solving this before. I
>>>> think the function needs to provide a way to tell if the value was
>>>> already present.
>>>
>>> Not as straightforward, but it can be done:
>>>
>>> bool inserted = false;
>>> auto p = aa.getOrAdd("key", {inserted = true; return new Person; });
>>
>> Let me say I was surprised that this doesn't actually work. An in-line
>> lambda will NOT work as a lazy parameter, even though that's EXACTLY
>> what a lazy parameter is implemented as! And variadic lazy parameters
>> are explicitly typed this way.
>>
>> Has that ever worked? I could have sworn it did...
> 
> I'm not sure. I mucked around with lazy like this when I was originally
> working on stuff like assertThrown and assertPred 7 or 8 years ago, but I've
> done _very_ little with lazy since then. My gut reaction is that it worked,
> but it might not have. If you add parens after it so that you call it, it
> does work, since then the result is the correct type. And if you ignore the
> exact details of how lazy is implemented and consider that it's supposed to
> take an expression that evaluates to a specific type, a lambda doesn't match
> that unless it's called. So, it does make sense from that perspective and is
> likely why it works the way it does.

But, it *is* a delegate. literally, that's what gets implemented (and it 
has to be that way). I suppose if it's inlined, the compiler could take 
some leeway, but that is the same with a delegate literal passed to a 
function that takes a delegate anyway.

The fact that lazy variadics are explicitly delegates makes this even 
more annoying. I wish we could have the best of both worlds (non-ugly 
calls inside the function, and easy binding to whatever you want at the 
call side). I'm not even sure why lazy variadics are the way they are, I 
can instantly think of a better syntax for them.

> The compiler would basically have to
> special-case delegates to accept stuff like lambdas when the type of the
> lazy parameter is not a delegate. And if it _did_ special-case it, then
> things might get interesting if you actually had a lazy parameter that was a
> delegate.

This is pretty easy, does your delegate return a delegate or an int? ;)

This is a super-solvable problem, I'm just surprised it wasn't this way 
before, I could have sworn I've done this in the past.

> So, I don't know if it should work or not, but the workaround is
> pretty simple - just add parens to call it.

This results in a double delegate call -- the compiler makes a delegate 
that calls your delegate. Not optimal, but yes it does work.

-Steve


More information about the Digitalmars-d mailing list