Passing functions to functionals

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Wed Dec 1 01:22:59 PST 2010


On Tue, 30 Nov 2010 18:49:56 +0300, Dmitry Olshansky wrote:

> On 30.11.2010 14:59, Lars T. Kyllingstad wrote:
>> In my library I have a lot of functionals (functions that take other
>> functions as parameters).  Here is an example that shows the style I
>> use to define them:
>>
>>      // Example: Evaluate the function/delegate/functor f at x. auto
>>      eval(F, X)(F f, X x) { return f(x); }
>>
>>      // Test
>>      void main()
>>      {
>>          int add2(int i) { return i + 2; }
>>          assert (eval(&add2, 1) == 3);
>>      }
>>
>> In other words, the function is passed as a run-time parameter.  I've
>> seen this (or similar) style used in Phobos, but there, I've also noted
>> that functions are sometimes passed as template alias parameters:
>>
>>      // Same as above, using template alias parameter. auto eval(alias
>>      f, X)(X x) { return f(x); }
>>
>>      // Test
>>      void main()
>>      {
>>          int add2(int i) { return i + 2; }
>>          assert (eval!add2(1) == 3);
>>      }
>>
>> I'd be grateful if people would share their knowledge of the pros and
>> cons of each method.  For instance, are there any situations where
>> template alias parameters don't work?
>>
>>
>> Thanks,
>>
>> -Lars
> alias parameters must be know/computable at compile time, quick example
> on what you can't do:
> 
> import std.stdio;
> 
> auto eval(F, X)(F f, X x) { return f(x); } auto eval2(alias f,X)(X x){
> return f(x); }
> 
> auto summator(int k){
>      int f(int val){
>          return k + val;
>      }
>      return &f;
> }
> 
> 
>   // Test
> void main()
> {
>       int add2(int i) { return i + 2; }
>      int traceAdd2(int i){
>          writeln(i," --> ",i+2);
>          return i+2;
>      }
>      int delegate(int) getAdd2(){
>          writeln("Getting add2");
>          return &add2;
>      }
>       assert(eval(&add2, 1) == 3);
>       assert(eval2!add2(1) == 3);
>      assert(eval(summator(2),1) == 3);
>      //Next one fails with
>      //Error: closures are not yet supported in CTFE //Error: cannot
>      evaluate summator(2) at compile time
>      //assert(eval2!(summator(2))(1) == 3);
> 
>      assert(eval(&traceAdd2,1) == 3);
>      assert(eval2!traceAdd2(1) == 3); //side effect in call is no
>      problem
> 
>      assert(eval(getAdd2,1) == 3);
>      //Next one fails with
>      //Error: cannot evaluate writeln("Getting add2") at compile time
>      //Error: cannot evaluate getAdd2() at compile time
>      //assert(eval2!(getAdd2())(1) == 3);
> }

That's a very good point, and pretty much settles it for me.  I'll stay 
away from alias parameters, then.  Thanks!

-Lars


More information about the Digitalmars-d-learn mailing list