Thread overview
How can I do lazy variable initialization?
Jan 09, 2021
Jack
Jan 09, 2021
Ali Çehreli
Jan 09, 2021
Ali Çehreli
Jan 09, 2021
Jack
January 09, 2021
In c# we can do something like this:


>  static Lazy<T> lazy =
>        new Lazy<T>
>            (() => heavyLoadOperation());
>  static T value { get { return lazy.Value; } }

and heavyLoadOperation() is only called when variable "value" is actually used. How can I do something like this in D?

I've tried something like this I still can't make it compile:

>T delegate() lazy lazy = { return heavyOperation(); }
>T X(lazy T delegate() dg) { return dg(); }
>T value = X;


January 09, 2021
Explicit with a lambda:

import std;

int heavyLoadOperation() {
  writeln("Expensive!");
  return uniform(0, 10);
}

void main(string[] args) {
  const l = {
    bool inited = false;
    static int i;
    if (!inited) {
      i = heavyLoadOperation();
    }
    return i;
  }();

  if (args.length == 1) {
    writefln!"Using lazy variable: %s %s"(l, l);
  }
}

Getting help from memoize (this one is lovely):

alias lightLoadOperation = memoize!heavyLoadOperation;

  const l = lightLoadOperation();

And of course, the first approach can be wrapped in a type like C#'s lazy as well.

Ali

January 09, 2021
On 1/9/21 12:35 PM, Ali Çehreli wrote:

> alias lightLoadOperation = memoize!heavyLoadOperation;
>
>    const l = lightLoadOperation();

Well, that doesn't work the way you want but this does:

  if (args.length == 1) {
    writefln!"Using lazy variable: %s %s"(lightLoadOperation(), lightLoadOperation());
  }

No matter how many times you call lightLoadOperation, it will be called just once (which can be configured with maxSize):

  https://dlang.org/library/std/functional/memoize.html

Ali


January 09, 2021
On Saturday, 9 January 2021 at 20:39:26 UTC, Ali Çehreli wrote:
> On 1/9/21 12:35 PM, Ali Çehreli wrote:
>
> > alias lightLoadOperation = memoize!heavyLoadOperation;
> >
> >    const l = lightLoadOperation();
>
> Well, that doesn't work the way you want but this does:
>
>   if (args.length == 1) {
>     writefln!"Using lazy variable: %s %s"(lightLoadOperation(), lightLoadOperation());
>   }
>
> No matter how many times you call lightLoadOperation, it will be called just once (which can be configured with maxSize):
>
>   https://dlang.org/library/std/functional/memoize.html
>
> Ali

In case of a function that takes no arguments ever, using memoize may add memory overhead and something like this:

bool loaded = false;
T heavyLoadOperation() {
  if(!loaded) {
     // ... heavy operation.
    loaded = true;
  }
  return value;
}


can actually be better in terms of memory usage? I thought the lazy keyword could somehow help here but I think the way to go is is just use a flag, such as loaded bool variable.