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