August 18, 2006
kris wrote:
> xs0 wrote:
>> Well, to me it seems that anything the compiler will try to do automatically will be wrong (or at least needlessly slow) in many cases. And a lot of the problem seems to be simply that one can't attach storage to a delegate without creating a whole class/struct, and doing that is too verbose to be used easily/often.
>>
>> So, why not simply have some syntax sugar for that?
>>
>> int delegate() fibs()
>> {
>>     int a=0, b=1;
>>     return delegate with(a,b) { // it takes a and b with it
>>         ...
>>     }
>> }
> 
> Nice, but the problem with that is as follows:
> 
> When passing such a delegate as an argument, you don't know whether it'll be used in a synchronous or asynchronous manner.

Are you sure you don't know? I can't think of a case where I'd be in doubt..


> So, perhaps you choose the safe route and assume worst-case. That's cool, but if you choose best case instead (because you 'know' usage is synchronous) then you leave yourself open to nasty issues if that callee is ever changed. Think about passing a delegate to a third-party lib? The contract is weak, and therefore fragile. That's why we'd suggested an extension to the type system instead (which also has some problems).

Well, I think it's not as big a problem realistically.. When you provide a delegate you need to know what its purpose is and I think that is something very unlikely to change. The two main types of delegates seem to be callbacks and specific operations for generic algorithms. I don't see how a library update would change the contract between those two.


> The other thing that Mik noted is that the entire frame should be on the heap; not just part of it (for performance reasons)

What performance reasons? I read this entire thread and still have no idea how copying more/all of the frame could/would be faster..


> , and taking a snapshot copy of the scope (or part thereof) does not work at all, since there could be self-references, pointers, whatever, in there. It seems you have to flip the entire frame into the heap.

The semantics are clear - the current values of the with() variables get copied at the point where the delegate literal becomes "instantiated"; whatever you put there is up to you..


xs0
August 18, 2006
xs0 wrote:
> Mikola Lysenko wrote:
>> [snip]
>> Any thoughts or comments?
> 
> Well, to me it seems that anything the compiler will try to do automatically will be wrong (or at least needlessly slow) in many cases. And a lot of the problem seems to be simply that one can't attach storage to a delegate without creating a whole class/struct, and doing that is too verbose to be used easily/often.
> 
> So, why not simply have some syntax sugar for that?
> 
> int delegate() fibs()
> {
>     int a=0, b=1;
>     return delegate with(a,b) { // it takes a and b with it
>         ...
>     }
> }
> 
> Which would become exactly what you proposed.
> 
> 
> xs0

Would the instances of a & b of the fibs function be the same as the ones in the delegate? In other words, does the "with(a,b)" create a heap copy of a & b, for the delegate to use, or does it cause the original "int a=0, b=1;" to be heap allocated?


-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
August 18, 2006
Bruno Medeiros wrote:
> xs0 wrote:
>> Mikola Lysenko wrote:
>>> [snip]
>>> Any thoughts or comments?
>>
>> Well, to me it seems that anything the compiler will try to do automatically will be wrong (or at least needlessly slow) in many cases. And a lot of the problem seems to be simply that one can't attach storage to a delegate without creating a whole class/struct, and doing that is too verbose to be used easily/often.
>>
>> So, why not simply have some syntax sugar for that?
>>
>> int delegate() fibs()
>> {
>>     int a=0, b=1;
>>     return delegate with(a,b) { // it takes a and b with it
>>         ...
>>     }
>> }
>>
>> Which would become exactly what you proposed.
>>
>>
>> xs0
> 
> Would the instances of a & b of the fibs function be the same as the ones in the delegate? In other words, does the "with(a,b)" create a heap copy of a & b, for the delegate to use, or does it cause the original "int a=0, b=1;" to be heap allocated?

A heap copy is created at the point in code where the delegate is "evaluated". For example, the above case would function exactly the same as the following:

int delegate() fibs()
{
    int a=0, b=1;
    auto result = delegate with(a,b) {
        ...
    }
    a = 5000;
    b = -1;
    return result;
}

because it would become this behind the scenes:

class _anonymousclass123 // more probably struct
{
    int a, b;
    this(int a, int b) {
        this.a=a; this.b=b;
    }

    int _anonymousfunc() {
        ...
    }
}

int delegate() fibs()
{
    int a=0, b=1;
    auto result = &((new _anonymousclass123(a, b))._anonymousfunc);
    a = 5000;
    b = -1;
    return result;
}

Of course, the compiler is free to allocate the fibs()'s a and b on the heap, if it determines the result is the same (it's potentially better because less stack is used), though I don't think it would actually matter in any realistic case..


xs0
August 24, 2006
BCS wrote:

> because this is so much slower, I would hate to see it happen silently. Having a function use a heap-frame just because I add a delegate could cause some hard to track down performance hits. I would advocate making the escaping delegate illegal unless the code explicitly says to put /part/ or all of the frame on the heap.

Wow, the concept of putting only *part* of the frame on the heap really blew my mind.  It suggests the following syntax:

void foo() {
  int a;   // on stack

  heap {  // all variables in this scope on the heap
    ...stuff...
  }
}
1 2 3 4 5 6
Next ›   Last »