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

Reply via email to