2014-05-30 39 views
7

我需要执行N次操作。 D做最好的方法是什么?如何重复一次语句N次(简单循环)

for(uint i=0; i<N; i++) 
    action(); 

foreach(uint i; 0.. N) 
    action(); 

也许更好?理想的情况是我想要的东西像Groovy的/ Ruby的times e.g

N.times { 
    action(); 
} 

这可能吗?

+1

顺便说一句,你的第二个例子中必须使用'foreach'而不是'for'实际上,你可以删除'uint'。 D中用于循环迭代器的约定不需要在循环中引用,因此将其命名为“_”。所以它变成了'foreach(_; 0 .. N)' – yaz

+0

我真的推荐下载免费的参考资料并阅读它。所有这些在本书的早期就已经得到了回答。你的第一部作品。你的第二个是0..N {...}中的_。第三个是可能的,但我不确定时间延长是否正常。我知道在WWDC演示文稿中有这样的例子,我认为Swift入门。 –

回答

10

是的,这是可能的

import std.stdio; 
import std.traits; 

void foo() 
{ 
    writeln("Do It!"); 
} 

void times(T,N)(N n, T action) if (isCallable!T && isIntegral!N) 
{ 
    static if (ParameterTypeTuple!action.length == 1 
      && isIntegral!(ParameterTypeTuple!action[0])) 
     foreach (i; 0 .. n) 
      action(i); 
    else 
     foreach (i; 0 .. n) 
      action(); 
} 

void main(string[] args) 
{ 
    10.times(&foo); 
    10.times({writeln("Do It!");}); 
    10.times((uint n){writeln(n + 1, " Round");}); 
} 

版本的论证支持:

import std.stdio; 
import std.traits; 

void foo() 
{ 
    writeln("Do It!"); 
} 

struct Step { 
    alias n this; 
    size_t n; 
    this(size_t i) 
    { 
     n = i + 1; 
    } 
} 

struct Index { 
    alias n this; 
    size_t n; 
} 

void times(T,N,A...)(N n, T action, A args) if (isCallable!T && isIntegral!N) 
{ 
    alias PTTAction = ParameterTypeTuple!action; 
    static if (PTTAction.length >= 1) 
    { 
     alias FP = PTTAction[0]; 
     static if (is(Index == FP) || is(Step == FP)) 
      foreach (i; 0 .. n) 
       action(FP(i), args); 
     else 
      action(args); 
    } 
    else 
     foreach (i; 0 .. n) 
      action(); 
} 

void main(string[] args) 
{ 
    10.times(&foo); 
    10.times({writeln("Do It!");}); 
    10.times((Step n){writeln(n, " Step");}); 
    10.times((Index n, string msg){writeln(n, msg);}, " Index"); 
    stdin.readln; 
} 

UPDATE:

有更好的表现,你可以使用别名模板parametr行动:

void times(alias action,N)(N n) if (isCallable!action && isIntegral!N) 
{ 
    static if (ParameterTypeTuple!action.length == 1 
      && isIntegral!(ParameterTypeTuple!action[0])) 
     foreach (i; 0 .. n) 
      action(i); 
    else 
     foreach (i; 0 .. n) 
      action(); 
} 

void main(string[] args) 
{ 
    10.times!(foo); 
    10.times!({writeln("Do It!");}); 
    10.times!((uint n){writeln(n + 1, " Round");}); 
} 
+0

好的,谢谢:-)特别是第一个版本非常简单,我很喜欢。 – Parobay

+0

你能写出为什么表现可能会更好吗? – Parobay

+0

由于按名称传递(别名操作)不需要取消引用操作。但我不确定。也许有更多的原因,所以这将是interresing使这个单独的问题。 – Kozzi11

4

也许这样?

void loop(int n, void delegate() func) 
{ 
    foreach (i; 0 .. n) 
    { 
     func(); 
    } 
} 

用法:

loop(10, {   
    writeln("Hello World!"); 
});