D言語のおはなし
※この記事は ICT Advent Calendar 2018 18日目の記事です.
昨日はICUに合格したらしいまなえです.
明日は,私が高専を去ることを心底悲しんでいるkurokojiです.
親しい人が離れていくというのは正直寂しいですよ.はい.
毎年私からの愛のこもったフリを受けるために,私の次の日に記事を書いちゃう可愛いやつです.
誤りがあるので言っておくと,僕のほうが先に18日に書く予定を入れていたのに,17日に後からわざと入れたのはあなたでしょ??? 事実を曲げることは良くないです.
D言語を流行らせたい
全人類が学ぶべき言語であるところのD言語.しかし実態はあまり知られていないように思います.
D言語くんは知っていますか?
Twitter等で一度は見たことがあると思います.何かと変なポーズなので,ほとんどの人が笑いの対象としか見ていないような気はしますが.
「変なマスコットキャラクターが存在する,ようわからん言語」
そのイメージを払拭するために,このD言語販促記事を書いてます.
あ,ちなみに今年の高専プロコン競技部門のソルバはD言語で書かれています.
https://github.com/kurokoji/procon29-kyogi/tree/master/nagatogithub.com
軽い文法の紹介
import std.stdio, std.array; void main() { writeln("Hello, World!!"); for (size_t i = 0; i < 10; ++i) { writeln(i); } /* 上のfor文と同じ動きをする foreachの場合,iの型は何も書かなくても型推論してくれます */ foreach (i; 0 .. 10) { writeln(i); } uint[] ar = [1, 2, 3, 4, 5]; ar[0 .. 3] = 0; // [0, 0, 0, 4, 5] ar[0 .. $] = 6; // [6, 6, 6, 6, 6] }
import std.stdio
はC,C++でいう #include <stdio.h>
みたいなもの.厳密には違うけど,まぁそれは置いておいて.
writeln
が printf
のような標準出力関数です.writeln
は改行が最後に勝手に入ります.write
なら入りません.
writeln
は printf
と違って書式文字列("%s %s"
みたいな)は使えませんが,writefln
で同様に出来ます.
一般的な for
も使えますが foreach
も使えます.
C,C++などと違って,unsigned int
は uint
です.短くて良い.
で,ar[0 .. 3] = 0
みたいに配列のここから,ここまで0を代入する,みたいなのが一行で分かりやすく書けます.
if
などは他の言語と大体一緒です.
面白い機能の紹介
D言語には面白い(しかも便利)機能がたくさんあります.
- UFCS(統一関数呼び出し構文)
- CTFE(コンパイル時関数実行)
- Range
- unittest
- mixin
- traits
- TMP(テンプレートメタプログラミング)
などなど.
いくつか紹介します.
UFCS(統一関数呼び出し構文)
import std.stdio; int inc(int a) { return a + 1; } void main() { int n = 1; writeln(inc(n)); // 2 writeln(n.inc()) // 2 }
writeln(inc(n))
は普通ですね.
writeln(n.inc())
に注目していただきたい.
UFCSとは関数の第1引数を関数の前に持ってきて,まるでメンバ関数のように振る舞うことが出来る構文です. これによりメソッドチェーンがやりやすくなり,見た目もよりキレイになります.
CTFE(コンパイル時関数実行)
import std.stdio, std.string, std.conv; bool[] Eratosthenes(ulong N)() { bool[] is_prime = new bool[N + 1]; is_prime[2 .. $] = true; for (ulong i = 2; i * i <= N; ++i) { if (is_prime[i]) { for (ulong j = i * 2; j <= N; j += i) { is_prime[j] = false; } } } return is_prime; } void main() { // enumをつけることで,強制的にCTFEを発動させることが出来ます enum tmp = Eratosthenes!100000; write(">> "); auto n = readln.chomp.to!uint; writeln(tmp[n]); }
readln.chomp.to!uint
は標準入力から一行文字列を受け取って,改行を取り除き,uint
に変換しています.
このプログラムはエラトステネスの篩という素数を列挙するアルゴリズムです.
通常,この計算はN
が大きくなると計算が遅くなります.そこで,CTFE(コンパイル時関数実行)を用いると高速化が見込めます.
名前の通り,この機能はコンパイル時に関数を実行,つまり計算を行っています. これにより,実行時は列挙部分の計算は行わないため,高速化が可能です.
ただし,計算結果を埋め込むことになるので吐いたバイナリのサイズは大きくなります.
mixin
void main() { mixin("writeln(1);"); }
見慣れないものが出てきました. これをコンパイルして実行すると,1
と出力されます.
mixin
は渡された引数の文字列をその場所にDのコードとして埋め込むことが出来ます. (条件がありますが,詳しい説明は省きます)
例えば,四則演算をする関数を作りたいと思ったとき.
int calc(string op)(int lhs, int rhs) { // Dでは~(チルダ)で文字列の連結が出来る return mixin("lhs" ~ op ~ "rhs"); } void main() { writeln(calc!"+"(1, 2)); // 3 writeln(calc!"-"(3, 1)); // 2 writeln(calc!"*"(3, 4)); // 12 writeln(calc!"/"(8, 2)); // 4 }
このようにすると関数を4つも書かなくて済みますね.
D言語に興味を持ったそこのあなた
Windows/Mac/Linux に対応してるので今すぐインストール. ここ
curl -fsS https://dlang.org/install.sh | bash -s
これらのD言語の魅力は使ってみて体感してください.特にC++ユーザーは気にいるはず.
明日はバターくんです.(誰かわからんぞ)
// ここに記事を貼る