digitalmars.D - Lazy evaluation
- OF (35/35) Jun 27 2007 Hey. I've been writing a bit on a "true" lazy evaluation (i.e. not evalu...
- BCS (5/6) Jun 27 2007 This is the /exact/ behavior of delegate liters and delegates formed
- Lutger (2/10) Jun 27 2007 Yeah, but only when you access some variables through this pointer right...
- BCS (3/18) Jun 27 2007 I would assume so but there might be some hidden reads that could cause
- Lutger (4/23) Jun 27 2007 Could you elaborate? I see nothing in the spec that says it's legal or
- BCS (42/73) Jun 27 2007 I known of no cases where hidden read/writes happen, but unless the spec...
- Regan Heath (3/14) Jun 28 2007 If you don't need to do that then you want a function as opposed to a de...
- Frits van Bommel (6/7) Jun 28 2007 Yes, function literals are possible. And indeed, they have 'function' in...
- OF (13/20) Jun 28 2007 Yes, you're right. It's probably the delegate created in
- Jarrett Billingsley (3/6) Jun 27 2007 Nope. D doesn't have implicit casting as in C++.
- David B. Held (3/10) Jun 27 2007 ...yet.
- Robert Fraser (2/14) Jun 27 2007
- Jarrett Billingsley (2/3) Jun 28 2007 So just how far is Walter going to go to please C++ programmers? :P
- David B. Held (10/15) Jun 28 2007 The problem is proxy types. Proxy types happen to be useful, and in
-
Stewart Gordon
(17/25)
Jun 29 2007
- OF (2/4) Jun 29 2007 Using this it works fine. Thank you.
Hey. I've been writing a bit on a "true" lazy evaluation (i.e. not evaluated until value is requested, but only evaluated once). A simple example of this can be achieved using a delegate, like so: template Lazy(T) { class Lazy { this(T delegate() exp) { mExp = exp; } T opCall() { if (!mEvaluated) { mValue = mExp(); mEvaluated = true; } return mValue; } private: bool mEvaluated = false; final T delegate() mExp; T mValue; } } Which would work fine with Lazy!(int)( { return someExpr; } ), but it would be nice to be able to just use Lazy!(int)( someExpr ). However, it seems this can only be achieved using lazy function arguments, but problem is, if I use lazy function arguments, I can't really save it for later and do anything worthwhile with it. Consider the additional constructor this(lazy T lazyexp) { mExp = { return lazyexp; }; } which looks fine, but isn't (it crashed with Access Violation). It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates. Yet the article about lazy evaluation ( http://www.digitalmars.com/d/1.0/lazy-evaluation.html ) seems to indicate lazy is just syntetic sugar for delegates... but the behaviour is not like it at all. It doesn't seem to be able to convert a lazy expression to an delegate in any way (cast complains, the above, as said, crashes). Is there any way I've missed? In addition, the above mentioned article states "So D takes it one small, but crucial, step further (suggested by Andrei Alexandrescu). Any expression can be implicitly converted to a delegate that returns either void or the type of the expression." which doesn't seem to be true either, or it would be enough with the first constructor that just uses the normal delegate syntax. Had this worked, it would have been fine for this case. An other alternative I thought of was to save the lazy expression in the Lazy object instead of the delegate, but lazy seems to be completely restricted to function arguments. Is there any specific reason for this? I mean, "lazy int i = j++;" in, for example, a function isn't that much weirder. It's still just seems to be syntetic sugar for delegates, it should be able to work consistently with the behaviour of lazy for function arguments, should it not? Any explanations or suggestions are welcome. Slightly unrelated, is there anything in D corresponding to C++'s implicit cast operators (operator 'typename'(), e.g. operator int()) in D? I can't seem to find any...
Jun 27 2007
OF wrote:It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 27 2007
BCS wrote:OF wrote:Yeah, but only when you access some variables through this pointer right?It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 27 2007
Lutger wrote:BCS wrote:I would assume so but there might be some hidden reads that could cause problems.OF wrote:Yeah, but only when you access some variables through this pointer right?It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 27 2007
BCS wrote:Lutger wrote:Could you elaborate? I see nothing in the spec that says it's legal or not. If there are problems with this, I think that should be clearly stated.BCS wrote:I would assume so but there might be some hidden reads that could cause problems.OF wrote:Yeah, but only when you access some variables through this pointer right?It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 27 2007
Lutger wrote:BCS wrote:I known of no cases where hidden read/writes happen, but unless the spec says so, I would not assume they don't happen if I could avoid it. The spec does say that a delegate to a nested function is invalid after the function returns (note nothing about if it access anything). <start rant> This is one reason where I would really like to see explicit contexts for delegate literals class C{ int i; int j; } void main(){ C c = new C; void delegate (int, int) set = c.(int k, int l){ i=k; j=l; // access any public parts of the thing }; // delegate literal without risk of stack corruption void delegate() action = null.{someGlobalAction();}; int i = 5; bool delegate(int) test = i.(int j){ return this == j; // why not int for context? }; // sizeof(int) == sizeof(void*) // now how about 32bit structs by value? struct foo { short a; char b; byte c; } static assert(sizeof(foo) == sizeof(void*)); foo dat = foo(45, 'c', 222) int delegate() go_v = dat.{return a+b+c;}; // now by reference int delegate() go_p = (&dat).{return a+b+c;}; dat.a = 0; dat.b = '\0'; dat.c = 0; assert(go_v != 0); assert(go_p == 0); }Lutger wrote:Could you elaborate? I see nothing in the spec that says it's legal or not. If there are problems with this, I think that should be clearly stated.BCS wrote:I would assume so but there might be some hidden reads that could cause problems.OF wrote:Yeah, but only when you access some variables through this pointer right?It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 27 2007
Lutger Wrote:BCS wrote:If you don't need to do that then you want a function as opposed to a delegate, right? Is such a thing possible in D, function literals. You might need to explicitly say 'function' in there somewhere. I've not used these a heck of a lot so I'm not sure. ReganOF wrote:Yeah, but only when you access some variables through this pointer right?It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 28 2007
Regan Heath wrote:Is such a thing possible in D, function literals. You might need to explicitly say 'function' in there somewhere. I've not used these a heck of a lot so I'm not sure.Yes, function literals are possible. And indeed, they have 'function' in them. In fact, put 'function' in front of a delegate literal (and remove the optional 'delegate' if present) and you have a function literal. Details: http://www.digitalmars.com/d/expression.html#FunctionLiteral (or the equivalent 1.0 page)
Jun 28 2007
BCS Wrote:OF wrote:Yes, you're right. It's probably the delegate created in this(lazy T exp) { mExp = { return exp(); }; } that's the problem. this(T delegate() exp) { mExp = { return exp(); }; } crashes too. That's what I get for not doing my homework... I suppose my only hope would be some kind of casting from lazy T to T delegate(), but seems I'm out of luck.It hints at lazyexp not being valid after the function has ended, which makes it quite different from delegates.This is the /exact/ behavior of delegate liters and delegates formed from nested functions. They are invalid after the function call they are from returns. This is because the delegate caries a pointer to the stack frame of the surrounding function.
Jun 28 2007
"OF" <nospam nospammington.com> wrote in message news:f5u09a$1mmq$1 digitalmars.com...Slightly unrelated, is there anything in D corresponding to C++'s implicit cast operators (operator 'typename'(), e.g. operator int()) in D? I can't seem to find any...Nope. D doesn't have implicit casting as in C++.
Jun 27 2007
Jarrett Billingsley wrote:"OF" <nospam nospammington.com> wrote in message news:f5u09a$1mmq$1 digitalmars.com......yet. DaveSlightly unrelated, is there anything in D corresponding to C++'s implicit cast operators (operator 'typename'(), e.g. operator int()) in D? I can't seem to find any...Nope. D doesn't have implicit casting as in C++.
Jun 27 2007
I really hope it doesn't... there are a _few_ times where it'd be nice for two classes to be inter-operable (mostly for backwards-compatibility purposes), but the majority of the time (like most operator overloads to me...) it's just confusing. David B. Held Wrote:Jarrett Billingsley wrote:"OF" <nospam nospammington.com> wrote in message news:f5u09a$1mmq$1 digitalmars.com......yet. DaveSlightly unrelated, is there anything in D corresponding to C++'s implicit cast operators (operator 'typename'(), e.g. operator int()) in D? I can't seem to find any...Nope. D doesn't have implicit casting as in C++.
Jun 27 2007
"David B. Held" <dheld codelogicconsulting.com> wrote in message...yet.So just how far is Walter going to go to please C++ programmers? :P
Jun 28 2007
Jarrett Billingsley wrote:"David B. Held" <dheld codelogicconsulting.com> wrote in messageThe problem is proxy types. Proxy types happen to be useful, and in order for them to work properly, you basically need implicit casts. Want an example of proxy types not quite working properly? Think what happens when you do ++ on a property or think of the magic that happens when you do it on a builtin hash. That doesn't mean they will be implemented just like C++'s implicit casts; but if they fix these other holes in the language, as well as enabling a new pattern, isn't that a net win? Dave...yet.So just how far is Walter going to go to please C++ programmers? :P
Jun 28 2007
"OF" <nospam nospammington.com> wrote in message news:f5u09a$1mmq$1 digitalmars.com...Hey. I've been writing a bit on a "true" lazy evaluation (i.e. not evaluated until value is requested, but only evaluated once). A simple example of this can be achieved using a delegate, like so:<snip>Which would work fine with Lazy!(int)( { return someExpr; } ), but it would be nice to be able to just use Lazy!(int)( someExpr ). However, it seems this can only be achieved using lazy function arguments, but problem is, if I use lazy function arguments, I can't really save it for later and do anything worthwhile with it.<snip> Actually you can take advantage of the fact that lazy expressions can be used for variadic delegate parameters. this(T delegate()[1] exp...) { mExp = exp; } enables you to use Lazy!(int)(someExpr) I used this to make an Unlambda to D compiler, and it even made it straightforward to implement the d builtin (which David Madore thought would be very hard to compile). Now the only thing that's left is getting c working properly. Stewart.
Jun 29 2007
Stewart Gordon Wrote:Actually you can take advantage of the fact that lazy expressions can be used for variadic delegate parameters.Using this it works fine. Thank you.
Jun 29 2007