2014-05-30 3 views
7

Мне нужно выполнить действие N раз. Каков наилучший способ сделать это?Как повторить инструкцию N раз (простой цикл)

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

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

может быть что-то лучше? В идеале я бы хотел что-то вроде в Groovy/Руби times например

N.times { 
    action(); 
} 

это возможно?

+1

Btw, ваш второй пример должен использовать '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

Поскольку передача по имени (псевдоним) не требует действия разыменования. Но я не уверен. И, может быть, есть еще несколько причин, так что это будет interreing сделать это отдельный вопрос. – Kozzi11

4

Возможно, что-то вроде этого?

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

Использование:

loop(10, {   
    writeln("Hello World!"); 
}); 
Смежные вопросы