title: What's the proper way to have a Task that calls an arbitrary function with a known, specific return type?
body: <p>I have a value which is expensive to calculate and can be asked for ahead of time--something like a lazily initiated value whose initialization is actually done at the moment of definition, but in a different thread. My immediate thought was to use <a href="https://dlang.org/phobos/std_parallelism.html" rel="nofollow noreferrer">parallelism</a>.-Task seems purpose-built for this exact use-case. So, let's put it in a class:</p>
  <pre class="lang-d prettyprint-override"><code>class Foo
  {
      import std.parallelism : Task,task;
      static int calculate(int a, int b)
      {
          return a+b;
      }
      private Task!(calculate,int,int)* ourTask;
      private int _val;
      int val()
      {
          return ourTask.workForce();
      }
      this(int a, int b)
      {
          ourTask = task!calculate(a,b);
      }
  }
  </code></pre>
  <p>That seems all well and good... except when I want the task to be based on a non-static method, in which case I want to make the task a delegate, in which case I start having to do stuff like this:</p>
  <pre class="lang-d prettyprint-override"><code>private typeof(task(&amp;classFunc)) working;
  </code></pre>
  <p>And <em>then</em>, as it turns out, <code>typeof(task(&amp;classFunc))</code>, when it's asked for outside of a function body, is actually <code>Task!(run,ReturnType!classFunc function(Parameters!classFunc))*</code>, which you may notice is <em>not the type actually returned by runtime function calls of that</em>. That would be <code>Task!(run,ReturnType!classFunc delegate(Parameters!classFunc))*</code>, which requires me to cast to <code>typeof(working)</code> when I actually call <code>task(&amp;classFunc)</code>. This is all extremely hackish feeling.</p>
  <p>This was my attempt at a general template solution:</p>
  <pre class="lang-d prettyprint-override"><code>/** 
      Provides a transparent wrapper that allows for lazy
      setting of variables. When lazySet!!func(args) is called
      on the value, the function will be called in a new thread;
      as soon as the value's access is attempted, it'll return the
      result of the task, blocking if it's not done calculating.
  
      Accessing the value is as simple as using it like the
      type it's templated for--see the unit test.
  */
  shared struct LazySet(T)
  {
  
      /// You can set the value directly, as normal--this throws away the current task.
      void opAssign(T n)
      {
          import core.atomic : atomicStore;
          working = false;
          atomicStore(_val,n);
      }
  
      import std.traits : ReturnType;
  /** 
      Called the same way as std.parallelism.task;
      after this is called, the next attempt to access
      the value will result in the value being set from
      the result of the given function before it's returned.
      If the task isn't done, it'll wait on the task to be done
      once accessed, using workForce.
  */
      void lazySet(alias func,Args...)(Args args)
          if(is(ReturnType!func == T))
      {
          import std.parallelism : task,taskPool;
          auto t = task!func(args);
          taskPool.put(t);
          curTask = (() =&gt; t.workForce);
          working = true;
      }
      /// ditto
      void lazySet(F,Args...)(F fpOrDelegate, ref Args args)
          if(is(ReturnType!F == T))
      {
          import std.parallelism : task,taskPool;
          auto t = task(fpOrDelegate,args);
          taskPool.put(t);
          curTask = (() =&gt; t.workForce);
          working = true;
      }
  
      private:
          T _val;
          T delegate() curTask;
          bool working = false;
  
          T val()
          {
              import core.atomic : atomicStore,atomicLoad;
              if(working)
              {
                  atomicStore(_val,curTask());
                  working = false;
              }
              return atomicLoad(_val);
          }
      // alias this is inherently public
      alias val this;
  }
  </code></pre>
  <p>This lets me call <code>lazySet</code> using any function, function pointer or delegate that returns T, and then it'll calculate the value in parallel and return it, fully calculated, next time anything tries to access the underlying value, exactly as I wanted. Unit tests I wrote to describe its functionality pass, etc., it works perfectly.</p>
  <p>But one thing's bothering me:</p>
  <pre class="lang-d prettyprint-override"><code>        curTask = (() =&gt; t.workForce);
  </code></pre>
  <p>Moving the <code>Task</code> around by way of creating a lambda on-the-spot that <em>happens</em> to have the <code>Task</code> in its context still seems like I'm trying to &quot;pull one over&quot; on the language, even if it's less &quot;hackish-feeling&quot; than all the casting from earlier.</p>
  <p>Am I missing some obvious language feature that would allow me to do this more &quot;elegantly&quot;?</p>