The future of lambda delegates

Oskar Linde olREM at OVEnada.kth.se
Wed Aug 16 18:07:17 PDT 2006


kris wrote:

> Oskar Linde wrote:
>> kris wrote:
>> 
>> 
>>>Yeah, this is a serious trap for the unwary and, unfortunately,
>>>prohibits the use of such delegates in the one place where the elegance
>>>would be most notable: as gui callbacks, per your example. As you say,
>>>the way around it (currently) is to create a class to house the 'scope'
>>>content, or otherwise refer to it. That's unweildy, even with
>>>anonymous-class syntax.
>>>
>>>If, as you suggest, D had some means to indicate that the scope should
>>>be placed on the heap instead of the stack, it would resolve the concern
>>>nicely. Perhaps that indication might be lambda syntax itself? For
>>>example, in C# the lambda indicator is the symbol '=>'
>> 
>> 
>> I don't think any special syntax is needed. I believe the compiler could
>> be able to automatically identify whether a function may have escaping
>> delegates referring to local variables.
>> 

I felt kind of stupid after posting this and finding out that everything
(and much more) had already been posted two hours earlier. 

> Yes, that's certainly one way. But the suggestion was to "take
> advantage" of an even simpler form of lambda delegates; one that C# 3.0
> is moving toward. It's worth taking a look at, just for comparitive
> purposes? Two random links:
> 
> http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees
> http://www.developer.com/net/csharp/article.php/3598381

Interesting. I always found the original D delegate syntax a bit too wordy,
and with the new delegate syntax, I think many of us noticed how a little
difference in typing overhead and clarity made the language feature much
more compelling. The reason is probably purely psychological, but the
result is there. Anyway, if you give a mouse a cookie... :)

If you want named and typed delegate arguments and a void return type, the
current syntax is probably close to optimal, but most of the delegates I
write are single expression functions. I think it is for those the C#3.0
lambda expression syntax was conceived. 

What in D is: 
(int a, int b) { return a + b; }

is in C#:
(a, b) => a + b;

You could theoretically go further if you were willing to accept anonymous
arguments. Something like:
$1 + $2

And some languages would even accept:
'+

While I really like how the short, concise C# lambda expression syntax
looks, I can't help but feel it is out of style with the rest of the
language. (It is probably just a very temporary feeling though). 

The => brings two features D's delegates doesn't have. 
1. The short form for the single expression case.
2. Implicitly typed arguments.

#1 is the easy part. #2 is not.

> On the other hand, one of the great things about the D compiler is it's
> voracious speed. If it turns out that automagically trying to figure out
> where the 'escapees' are will noticably slow the compiler down, then a
> bit of syntactic sugar might make all the difference :)

>From what little I know of compiler construction, escape analysis is
something that is done to all variables anyways. My guess is that most
delegate literals will end up escaping in some way or another, with the
most common case being passed as arguments to an external function. The
problem here is that the compiler can never know if that function intents
to keep the delegate reference till after the instantiating function has
returned.

Finding out which local or enclosing variables are referred to by escaping
delegates can't be that much harder, so I doubt compilation speed is an
issue. What could be an issue though is the fact that the compiler
defensively would have to heap allocate all variables any escaping
delegates refer to even though they in many cases never would be referenced
after the enclosing function returns.

What could improve things is if there was a no-immigrants (only visitors)
declaration for function arguments that guaranteed that any escaping
delegate passed to one such function argument would never be stored after
that function returns or be passed as argument to any other immigration
friendly function:

void update(int[] arr, visitor void delegate(inout int a) updater) {
        foreach(inout i;arr)
                updater(i);
}

...
int b = ...; 
myarr.update((inout int a) { a += b; }); 
// would not count as an escape and would not need b to be stack allocated

/Oskar




More information about the Digitalmars-d mailing list