Suggestion: "new delegate" - delegates useable outside of the nesting function scope

Burton Radons burton-radons at smocky.com
Sat Jun 3 04:50:04 PDT 2006


Walter Bright wrote:

> Burton Radons wrote:
> 
>> Walter Bright wrote:
>>
>>> Unfortunately, it's quite a bit more work than that. You have to copy 
>>> all the frames of the lexically enclosing functions, too. Then you 
>>> have the issue of updates to the framed variable copies not being 
>>> reflected in the stack variables. Then there's the problem of things 
>>> like:
>>>
>>>   int x;
>>>   int* px = &x;
>>
>>
>> Good points (I forgot about multiple nesting - did I ever compliment 
>> you for putting that in with the first release containing nested 
>> functions? - but you need to chain anyway so the logic must already be 
>> in there to piggyback onto), it is more work but compare it to the 
>> work required when it's omitted. I have done terrible things, 
>> committed sins against good engineering just because my nesting scope 
>> exits, and while it hasn't had a cooling effect on me, I'm sure there 
>> have been other people who have resorted to inferior Java 
>> class-inheritance techniques just to get around this problem. I have 
>> to admit I've done it once or twice. I was young and naive!
>>
>> Frozen variables are, of course, a feature, not a bug, and one the 
>> user would opt into by using the "new" variant. We discussed this in 
>> 2003. ;-) Anyway in three years and four months I haven't depended on 
>> the nesting scope's variables varying once, and while I haven't really 
>> wanted them to be frozen either, I've used it a few times in languages 
>> which freeze the nesting scopes (like Python).
>>
>> The only really good argument against this originally, in my opinion, 
>> was that it was a hidden allocation, but it's explicit like this.
> 
> 
> What about the px problem above? This wouldn't occur in Python which 
> doesn't have pointers, but it sure happens in D.

What about if the user calls a nested function outside of the nesting 
scope? They both have pitfalls.

I don't really want to mention it, but if you invert the logic it 
continues to act the same without this pitfall; the only change is that 
you can call the nested function outside of the nesting scope. What I 
mean is that instead of just passing the delegate a pointer to the 
frame, allocate the frame at the start if it or a nested scope has a 
"new delegate" and use that for both the delegate and that scope:

     float bar = 6;

     void delegate () dg = new delegate void () { bar = 8; }

Becomes:

     struct Delegate { void *self, func; }
     struct Frame { float bar; Delegate dg; }
     Frame *frame = new Frame;
     Delegate dg;

     frame.bar = 6;
     frame.dg = Delegate { frame,
         function void (Frame *frame) { frame.bar = 8; } };

Oh no, it's all syntax sugar! :-) The logic for doing this should mostly 
already be in the code. This might be well-justified because it makes 
nested functions behave consistently, and with some more effort it would 
only allocate a frame containing variables the nesting functions 
actually use.



More information about the Digitalmars-d mailing list