Jump to page: 1 2
Thread overview
lazy variables
Oct 17, 2018
aliak
Oct 17, 2018
Chris Katko
Oct 17, 2018
Ali Çehreli
Oct 18, 2018
aliak
Oct 17, 2018
Paul Backus
Oct 18, 2018
aliak
Oct 18, 2018
aliak
Oct 18, 2018
Paul Backus
Oct 18, 2018
Simen Kjærås
Oct 18, 2018
aliak
Oct 18, 2018
aliak
October 17, 2018
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




October 17, 2018
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
October 17, 2018
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

October 17, 2018
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();
}
October 18, 2018
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.
October 18, 2018
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
October 18, 2018
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?



October 18, 2018
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
October 18, 2018
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
October 18, 2018
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.
« First   ‹ Prev
1 2