まずはテンプレート制約を使ったコンパイル時fibonacci
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template fibo(int N) if (N < 2 && N >= 0) { | |
const long fibo = N; | |
} | |
template fibo(int N) if (N >= 2) { | |
const long fibo = fibo!(N - 1) + fibo!(N - 2); | |
} | |
template fibo(int N) if (N < 0) { | |
const long fibo = fibo!(N + 2) - fibo!(N + 1); | |
} | |
unittest { | |
assert(fibo!(0) == 0); | |
assert(fibo!(1) == 1); | |
assert(fibo!(2) == 1); | |
assert(fibo!(4) == 3); | |
assert(fibo!(7) == 13); | |
assert(fibo!(-1) == 1); | |
assert(fibo!(-2) == -1); | |
assert(fibo!(-3) == 2); | |
} | |
void main() { | |
import std.stdio; | |
fibo!(30).writeln; | |
} |
こんな風に、template temp(T) if(expr)みたいに書くと、if文で判定してテンプレートを適用してくれるみたいです。
これを使うと以前のstatic if文を使ったfizzbuzzも、
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template fizzbuzz(int N) if (N % 15 == 0) { | |
const fizzbuzz = "fizzbuzz"; | |
} | |
template fizzbuzz(int N) if (N % 3 == 0 && N % 5 != 0) { | |
const fizzbuzz = "fizz"; | |
} | |
template fizzbuzz(int N) if (N % 5 == 0 && N % 3 != 0) { | |
const fizzbuzz = "buzz"; | |
} | |
template fizzbuzz(int N) if(N % 3 && N % 5) { | |
import std.conv; | |
const fizzbuzz = N.to!string; | |
} | |
unittest { | |
assert(fizzbuzz!(1) == "1"); | |
assert(fizzbuzz!(3) == "fizz"); | |
assert(fizzbuzz!(5) == "buzz"); | |
assert(fizzbuzz!(15) == "fizzbuzz"); | |
assert(fizzbuzz!(33) == "fizz"); | |
assert(fizzbuzz!(60) == "fizzbuzz"); | |
} | |
void main() { | |
import std.stdio; | |
fizzbuzz!(15).writeln; | |
fizzbuzz!(3).writeln; | |
} |
static if文を並べるよりは綺麗に見えるんじゃないでしょうか。適用可能なテンプレートが複数あるとエラーになるので、if文がちょっとアレな感じはありますが。
ここで、以前書いたmixin FizzBuzzを見ると、(このコードだとmixinする意味が謎ですが)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
import std.conv; | |
string fizzbuzz(immutable ulong num) | |
{ | |
return (num % 15 == 0)? "FizzBuzz": (num % 3 == 0)? "Fizz": (num % 5 == 0)? "Buzz": num.to!string(); | |
} | |
string genfbtable(immutable ulong num) | |
{ | |
string ret = "[\"0\","; | |
for(ulong i = 1; i <= num; i++) | |
{ | |
ret ~= '"' ~ fizzbuzz(i) ~ '"'; | |
ret ~= i == num ? "]" : ","; | |
} | |
return ret; | |
} | |
void main() | |
{ | |
immutable ulong num = 100; | |
string[] table = mixin(genfbtable(num)); | |
for(ulong i = 1; i <= num; i++) | |
writeln(i, " ", table[i]); | |
} |
こんなふうにFizzBuzzの判定をする関数を作って利用してますが、D言語はコンパイル時に関数を実行出来るスゴイ奴があるので、
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
import std.conv; | |
string genFizzBuzzString(immutable ulong num) | |
{ | |
return (num % 15 == 0)? "fizzbuzz": (num % 3 == 0)? "fizz": (num % 5 == 0)? "buzz": num.to!string; | |
} | |
template fizzbuzz(ulong N) { | |
const fizzbuzz = genFizzBuzzString(N); | |
} | |
unittest { | |
assert(fizzbuzz!(1) == "1"); | |
assert(fizzbuzz!(3) == "fizz"); | |
assert(fizzbuzz!(5) == "buzz"); | |
assert(fizzbuzz!(15) == "fizzbuzz"); | |
assert(fizzbuzz!(33) == "fizz"); | |
assert(fizzbuzz!(60) == "fizzbuzz"); | |
} | |
void main() { | |
import std.stdio; | |
fizzbuzz!(15).writeln; | |
fizzbuzz!(3).writeln; | |
} |
このように何も考えなくてもコンパイル時fizzbuzzできますね。
fizzbuzzなんか書いてないで勉強しないといけないんですが。
※追記
早速ご指摘頂きました。
@rigibun dmd 2.064 から導入された eponymous template 使うと fizzbuzz をもっと短くできますね.
enum fizzbuzz(ulong N) = genFizzBuzzString(N);
— tom tan (@tm_tn) 2013, 12月 7
@rigibun すみません. ラムダ式使うと genFizzBuzzString も消せました. http://t.co/G1w1RtAu4V
— tom tan (@tm_tn) 2013, 12月 7
templateとか書かなくてもenum fizzbuzz ~ でいけるというdmd 2.064の新機能を使うようです。
さらにラムダを使うとgenFizzBuzzすら要らなかったという話。
究極的にはこれだけでいい
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.conv; | |
enum fizzbuzz(ulong N) = (num => (num % 15 == 0)? "fizzbuzz": | |
(num % 3 == 0)? "fizz": | |
(num % 5 == 0)? "buzz": | |
num.to!string)(N); |
D言語マジで頭おかしい
※更に追記
ラムダとか書かなくても3項演算子で代入する式書くだけだった!!!
@rigibun 度々すみません.ラムダ式すらいらなかったです. http://t.co/08biZbVWZZ D言語すごいな…
— tom tan (@tm_tn) 2013, 12月 7
0 件のコメント:
コメントを投稿