D言語のUFCSを使い倒す

こんにちは。 今回は、dmdに最近実装された機能であるUFCSを使って、AOJの簡単な問題をなるべくセミコロンを打たずに解いていきます。

簡単な問題ということで、Volume 0の0000番を選びました。

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0000&lang=jp


import std.stdio, std.range, std.algorithm, std.conv;

void main()
{
    1.iota(10).map!(a => 1.iota(10).map!(b => a.to!string() ~ "x" ~ b.to!string() ~ "=" ~ (a * b).to!string())().join("\n"))().join("\n").writeln();
}

D言語だと、セミコロンを2つしか打たずに、かつとても簡単にかけますね。 コードの中身を簡単に解説していきます。

上のコードは、iotaでまずRangeを2つ作り、それをto!stringで変換しつつうまく組み合わせて文字列を作っています。 そして、joinで改行をはさみつつ結果になる文字列を生成し、それをwritelnしています。

iotaは上記のようにまっとうな方法で使うこともできますが、まっとうじゃない方法で使うこともできます。


import std.stdio, std.range, std.algorithm;

void main()
{
    100.iota().map!(a => ("Hello, world!".writeln(), 0)).array();
}

上のコードは、Hello, world!と百行ほど出力するコードです。 100.iota()とやると、ちょうど要素の数が100のRangeが出来上がります。 それを利用して、そのRangeをmapして、mapの述語内で副作用のある操作をすると、 for文とおよそ同等のことができます。 最後にarrayでRangeを配列に変換している理由は、Rangeが遅延評価であるためです。

D言語だと、上のようにセミコロンを全く打たずにコードが書けて楽しいですね。