www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templates, varargs and static foreach

reply %u <user localhost.com> writes:
I would like to do the following:

void foo() {}
void bar(int a) { foo(); } // 1
void bar(int a, int b) { foo(); foo(); } // 2
void bar(int a, int b, int c) { foo(); foo(); foo(); } // 3
void bar(int[] a) { foreach(b; a) foo(); } // 4

The forms 1-3 should be called, when the amount of arguments is known at
compile time. Otherwise
4 is called.

Ok - this is a major simplification of the design I'm using. I would like to
shorten it using
templates. I have tried this:

void foo() {}
void bar(A...)(A a) { foo(); static if (a.length > 1) { bar(a[1..length]); }
void bar(A)(A[] a) { foreach(t;a) foo(); }

The problem is that the recursion happens on runtime (unless I specify -O
-release -inline). Can
the compiler guarantee that the recursion is unfolded, when all those
optimizations are on or is
there a static for/foreach for doing this in a better way.
Jan 14 2007
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
%u wrote:
 I would like to do the following:
 
 void foo() {}
 void bar(int a) { foo(); } // 1
 void bar(int a, int b) { foo(); foo(); } // 2
 void bar(int a, int b, int c) { foo(); foo(); foo(); } // 3
 void bar(int[] a) { foreach(b; a) foo(); } // 4
 
 The forms 1-3 should be called, when the amount of arguments is known at
compile time. Otherwise
 4 is called.
 
 Ok - this is a major simplification of the design I'm using. I would like to
shorten it using
 templates. I have tried this:
 
 void foo() {}
 void bar(A...)(A a) { foo(); static if (a.length > 1) { bar(a[1..length]); }
 void bar(A)(A[] a) { foreach(t;a) foo(); }
 
 The problem is that the recursion happens on runtime (unless I specify -O
-release -inline). Can
 the compiler guarantee that the recursion is unfolded, when all those
optimizations are on or is
 there a static for/foreach for doing this in a better way.

There is a "static foreach," only you do not use the "static" keyword. void foo() {} void bar(A...)(A a) { foreach(e; a) { foo(); } } You could also do this at runtime, using D's typesafe variadics: void bar(int[] a...) { foreach(e; a) { foo(); } } Both forms of bar are called in exactly the same way, with the caveat that the latter only accepts int arguments, while the former will accept any arguments. bar(1, 2, 3, 4); -- Kirk McDonald Pyd: Wrapping Python with D http://pyd.dsource.org
Jan 14 2007
parent reply %u <user localhost.com> writes:
There is a "static foreach," only you do not use
the "static" keyword.

 void foo() {}

 void bar(A...)(A a) {
      foreach(e; a) {
          foo();
      }
 }

Dear Kirk, I tried this too, but disassembling to code reveals that the foreach generates extra instructions when compared to this (dmd 1.00 linux): void bar(A...)(A a) { static if (a.length>0) foo(); static if (a.length>1) foo(); static if (a.length>2) foo(); static if (a.length>3) foo(); ... } I tried this without any optimizations. I just want to be sure that the compiler guarantees the behaviour at compile time. This function is time critical.
Jan 14 2007
parent %u <user localhost.com> writes:
 Dear Kirk, I tried this too, but disassembling to code reveals that the
foreach generates extra
 instructions when compared to this (dmd 1.00 linux):

The optimizer eliminates the extra code - not a problem anymore. I just wondered, why doesn't it do it all on compile time. Here's the dumbobj output: static if's: 0: 55 push %ebp 1: 8b ec mov %esp,%ebp 3: e8 fc ff ff ff call 4 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x4> 8: e8 fc ff ff ff call 9 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x9> d: e8 fc ff ff ff call e <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0xe> 12: e8 fc ff ff ff call 13 <_D2t216__T3abcTiTiTiTiZ3abcFiiiiZv+0x13> 17: 5d pop %ebp 18: c2 0c 00 ret $0xc 1b: 90 nop foreach: 0: 55 push %ebp 1: 8b ec mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 53 push %ebx 7: 89 45 fc mov %eax,0xfffffffc(%ebp) a: 8b 4d 10 mov 0x10(%ebp),%ecx d: e8 fc ff ff ff call e <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0xe> 12: 8b 45 0c mov 0xc(%ebp),%eax 15: e8 fc ff ff ff call 16 <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x16> 1a: 8b 55 08 mov 0x8(%ebp),%edx 1d: e8 fc ff ff ff call 1e <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x1e> 22: 8b 5d fc mov 0xfffffffc(%ebp),%ebx 25: e8 fc ff ff ff call 26 <_D2t216__T3bcdTiTiTiTiZ3bcdFiiiiZv+0x26> 2a: 5b pop %ebx 2b: c9 leave 2c: c2 0c 00 ret $0xc 2f: 90 nop
Jan 14 2007