Re: lazy variables
On 10/18/18 12:11 PM, aliak wrote: On Thursday, 18 October 2018 at 14:11:36 UTC, Steven Schveighoffer wrote: Yes, but that's what lazy variables do. Not in Swift at least... Apparently so (I have not used them before), but this is D! So you should be aware that lazy parameters work that way (the expression is evaluated each time the variable is used). In any case, you can certainly create a Swift-like lazy variable and I think the other responses probably show you the way. -Steve
Re: lazy variables
On Thursday, 18 October 2018 at 16:10:04 UTC, aliak wrote: On Thursday, 18 October 2018 at 14:16:56 UTC, Simen Kjærås wrote: On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? What the language doesn't provide, it generally provides the tools to make: struct Lazy(T) { T delegate() _payload; this(lazy T t) { _payload = () => t; } T get() { return _payload(); } alias get this; } int fun() { n++; return 2; } int n; unittest { Lazy!int a = 1 + fun(); assert(n == 0); // Ensure fun hasn't been called. auto b = a + 2; assert(b == 5); // Ensure calculation is correct. assert(n == 1); // Ensure fun has been called. } -- Simen yes! perfect! Thank you With single eval: struct Lazy(T) { private T delegate() _payload; private T _value; private bool set = false; this(lazy T t) { _payload = () { writeln("evaled"); return t; }; } @property T value() { if (!set) _value = _payload(); set = true; return _value; } @property void value(T newValue) { if (!set) _value = _payload(); set = true; _value = newValue; } alias value this; }
Re: lazy variables
On Thursday, 18 October 2018 at 14:16:56 UTC, Simen Kjærås wrote: On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? What the language doesn't provide, it generally provides the tools to make: struct Lazy(T) { T delegate() _payload; this(lazy T t) { _payload = () => t; } T get() { return _payload(); } alias get this; } int fun() { n++; return 2; } int n; unittest { Lazy!int a = 1 + fun(); assert(n == 0); // Ensure fun hasn't been called. auto b = a + 2; assert(b == 5); // Ensure calculation is correct. assert(n == 1); // Ensure fun has been called. } -- Simen yes! perfect! Thank you
Re: lazy variables
On Thursday, 18 October 2018 at 14:11:36 UTC, Steven Schveighoffer wrote: Yes, but that's what lazy variables do. -Steve Not in Swift at least...
Re: lazy variables
On Thursday, 18 October 2018 at 14:08:11 UTC, aliak wrote: On Wednesday, 17 October 2018 at 23:34:55 UTC, Paul Backus wrote: auto x = () { // do some heavy stuff }; if (condition) { func(x().y); // heavy stuff evaluated here } That would do heavy stuff everytime i wanted to get y though right? Yes. If that's a problem, you could use `std.functional.memoize`, or Ali's solution.
Re: lazy variables
On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? What the language doesn't provide, it generally provides the tools to make: struct Lazy(T) { T delegate() _payload; this(lazy T t) { _payload = () => t; } T get() { return _payload(); } alias get this; } int fun() { n++; return 2; } int n; unittest { Lazy!int a = 1 + fun(); assert(n == 0); // Ensure fun hasn't been called. auto b = a + 2; assert(b == 5); // Ensure calculation is correct. assert(n == 1); // Ensure fun has been called. } -- Simen
Re: lazy variables
On 10/18/18 10:08 AM, aliak wrote: On Wednesday, 17 October 2018 at 23:34:55 UTC, Paul Backus wrote: On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } auto x = () { // do some heavy stuff }; if (condition) { func(x().y); // heavy stuff evaluated here } That would do heavy stuff everytime i wanted to get y though right? Yes, but that's what lazy variables do. -Steve
Re: lazy variables
On Wednesday, 17 October 2018 at 23:34:55 UTC, Paul Backus wrote: On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } auto x = () { // do some heavy stuff }; if (condition) { func(x().y); // heavy stuff evaluated here } That would do heavy stuff everytime i wanted to get y though right?
Re: lazy variables
On 10/17/18 3:32 AM, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? i.e: struct S { //... int y; //... } /* lazy S x = () { // do some heavy stuff }(); */ auto x() { // do some heavy stuff } if (condition) { func(x.y); // heavy stuff evaluated here } -Steve
Re: lazy variables
On Wednesday, 17 October 2018 at 20:32:40 UTC, Ali Çehreli wrote: On 10/17/2018 12:32 AM, aliak wrote: [...] Not very clean but something like this: import std.stdio; struct LazyVar(alias exp) { alias T = typeof(exp()); T value() { static bool initialized = false; static T val; if (!initialized) { val = exp(); initialized = true; } return val; } alias value this; } LazyVar!(() { writeln("Doing heavy stuff"); return 42; }) a; void main() { auto b = a.value;// Must specify .value or int c = a; // must specify type of value (int). // Otherwise, b and c have type LazyVar!(...) // Some more usage b = c = a; assert(b == 42); assert(c == 42); } Ali Well I guess that's certainly a way to go about it :) Not very clean indeed though.
Re: lazy variables
On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } auto x = () { // do some heavy stuff }; if (condition) { func(x().y); // heavy stuff evaluated here } If you want to make it a little prettier, you could define a couple helper functions: T delegate() delay(lazy T expr) { return () => expr; } T force(T delegate() thunk) { return thunk(); }
Re: lazy variables
On 10/17/2018 12:32 AM, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? i.e: struct S { //... int y; //... } lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } Cheers, - Ali Not very clean but something like this: import std.stdio; struct LazyVar(alias exp) { alias T = typeof(exp()); T value() { static bool initialized = false; static T val; if (!initialized) { val = exp(); initialized = true; } return val; } alias value this; } LazyVar!(() { writeln("Doing heavy stuff"); return 42; }) a; void main() { auto b = a.value;// Must specify .value or int c = a; // must specify type of value (int). // Otherwise, b and c have type LazyVar!(...) // Some more usage b = c = a; assert(b == 42); assert(c == 42); } Ali
Re: lazy variables
On Wednesday, 17 October 2018 at 07:32:37 UTC, aliak wrote: Hi, Is there any notion of lazy vars in D (i see that there're parameters)? i.e: struct S { //... int y; //... } lazy S x = () { // do some heavy stuff }(); if (condition) { func(x.y); // heavy stuff evaluated here } Cheers, - Ali This might be helpful: https://dlang.org/articles/lazy-evaluation.html
Re: lazy variables cannot be lvalues - why?
On Monday, November 01, 2010 08:57:09 Adam Cigánek wrote: Hello, why is the following code illegal? import std.stdio; void delegate() fun; void capture(lazy void f) { fun = f; } void main() { capture(writeln(hello)); fun(); } It says Error: lazy variables cannot be lvalues, pointing to the fun = f line. It can be worked around by rewriting it like this: void capture(lazy void f) { fun = delegate void() { f(); }; } So it's not big deal, just a minor inconvenience. But still, why is it illegal? According to the docs (http://www.digitalmars.com/d/2.0/lazy-evaluation.html), lazy expressions are implicitly converted to delegates, so it seems to me that it should work. adam. 1. I 'm stunned that the compiler doesn't complain about you declaring f as void. It strikes me as a bug with lazy. You can't declare variables of type void. It makes no sense. 2. A lazy parameter is for all intents an purposes the exact same thing as a non-lazy parameter except that it's not actually calculated until the function is called. The fact that a delegate to make it lazy is used is an implementation detail. Use typeof on it, and you'll notice that its type is the same as if it weren't lazy, not a delegate. - Jonathan M Davis