本日は私、SHOOが某所に起稿した H.e.l.l.o. w.o.r.l.d! D
について解説いたします。
まずはそのプログラムをご覧に入れましょう
import std.string, std.range, std.algorithm, std.conv, std.array;
struct D
{
string msg;
D opDispatch(string s)() @property
{
return typeof(return)(
((a, b)=>a.equal(b))(
msg.retro().cycle().take(2),
msg.chain(s).retro().take(2).array().retro())
? ((a, b)=>(
a.insertInPlace(msg.countUntil(b)+1, ", "), a.idup)
)(msg.dup, msg.retro().take(2).array().retro())~s
: text(msg,s));
}
string d(T)() @property
{
return text(msg, T.stringof.toLower(), "! ", T.stringof);
}
}
struct H
{
static D opDispatch(string s)() @property { return D(typeof(this).stringof~s); }
}
pragma(msg, H.e.l.l.o. w.o.r.l.d! D);
void main() {}
"Hello, world!"はもう古い
過去の"Hello, world!"プログラムは
#include <stdio.h>
int main(int argc, const char *argv[])
{
printf("Hello, world! C\n");
return 0;
}
表示のために実行が必要
_人人人人人人_
> ダサい! <
 ̄^Y^Y^Y^Y^ ̄
D言語なら pragma(msg, ...)
やCTFE、テンプレートメタプログラミングを使うことで
コンパイル時に任意の処理を行った結果の表示が可能
pragma(msg, H.e.l.l.o. w.o.r.l.d! D);
_人人人人人人人人人人人人人人_
> こんなにもスタイリッシュ <
 ̄^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
経緯
○月×日 D言語が Dark Language だなんだとdisられる
夜、仕事から帰って、おもむろにTwitterをやった。
こいつら、Dark Languageだなんだときっとデマカセにちがいねェ。
俺たちをばかにしやがって。
○月△日 アンサイクロペディアの"Hello, world!"が壊れていることに気づく
今日、アンサイクロペディアの記事から昔の"Hello, world!"の世話を頼まれた。
皮をひんむいたJavaのような奴だ。
コードが通らないってんで、dmdに投げこんだら、奴ら、writelnのproperty文が通らなかったりDeprecationを引き出したり
喚いたあげくやっと死にやがる。
△月□日 UFCSの登場
今朝5時頃、宇宙服みてえなダブルクォーテーションを着た"Hello, world!"に突然たたき起こされて俺は興奮した。
なんでも、D言語に新機能の追加があったらしい。
コントリビューターの連中ときたら、夜も寝ないでコミットばかりやってるからこんな事になるんだ。
○月▽日 ダブルクォーテーションの削除を決意
昔からこのいまいましい宇宙服をつけたままなんで、背中がむれちまって妙にかゆい。
いらいらするんで、腹いせにあの"Hello, world!"のダブルクォーテーションを抜きにしてやった。
いい気味だ。
○月○日 UFCSとopDispatchの組み合わせ
あまりに背中がかゆいんで医務室にいったら、背中にでっけえopDispatchを貼られた。
それから、もう俺は宇宙服を着なくていいと医者がいった。
おかげで今夜はよく眠れそうだぜ。
○月◎日 セミコロンを使ったら負けかと思っている
朝起きたら、opDispatchだけでなくRangeにもUCFSができてやがった。
引用符の代わりにセミコロンがやけに煩いんで、足引きずって見に行ったら数が増えてる。
引用符を二個抜いたくらいで増えやがって。
おえら方に見つかったら大変だ。
○月◇日 特徴のある部分を使ってカンマ挿入位置を探す
昨日、このロジックから逃げ出そうとしたカンまが一つ、射さつされた、て はなしだ。
夜、からだ中 あついかゆい。
胸のはれ物 かきむしたら 肉がくさり落ちやがた。
いったいおれ どうな て
○月♡日 変数が必要ならラムダ式を使う
とくちょう みつ けた も とてもかゆい
変数 ひつようの、らむだ のしき つかう
○月⊿日 最後のエクスクラメーションはテンプレートを使って締めくくる
かゆい かゆい エクスクラメーションーきた
ひどいてんぷれなんて ころし
うまかっ です。
4
D言語
ウマー
解説(日本語OFFでお届けいたします)
import std.algorithm: equal;
unittest
{
// UCFS, equal
static assert("Hel".equal("Hel") == equal("Hel", "Hel"));
// lambda syntax
static assert( (a => a+1)(1) == 2 );
static assert( (a => a+1)(1) == (delegate int(int a){return a+1;})(1) );
static assert( (a => a+1)(1) == ((int a){return a+1;})(1) );
static assert( (a => a+1)(1) == ((a){return a+1;})(1) );
}
import std.algorithm;
import std.algorithm: countUntil;
import std.range: retro, cycle, take, array, chain;
unittest
{
// range compare
static assert( __traits(compiles, "leH" == "leH"));
static assert(!__traits(compiles, "Hel".retro() == "leH"));
static assert( __traits(compiles, "Hel".retro().equal("leH")));
static assert("Hel".retro().equal("leH"));
// retro
static assert("Hel".retro().equal("leH"));
// take
static assert("HelHelHelHelHelHelHel".take(7).equal("HelHelH"));
// cycle + take
static assert("Hel".cycle().take(7).equal("HelHelH"));
// chain
static assert("Hel".chain("l").equal("Hel" ~ "l"));
// countUntil
static assert("Hellowo".countUntil("ow") == "Hell".length);
// /*take + retro*/ take + array + retro
static assert(!__traits(compiles, "Hel".take(2).retro().equal("eH")));
static assert("Hel".take(2).array().retro().equal("eH"));
}
import std.array: insertInPlace;
unittest
{
/* insertInPlace ... (´・ω・`) */
string msg = "owo";
msg.insertInPlace(1, ", ");
assert(msg == "o, wo");
}
import std.array;
unittest
{
/* lambda + insertInPlace ... (`・ω・´) */
static assert((a=>(a.insertInPlace(1, ", "), a))("owo".dup) == "o, wo");
}
import std.conv: text, toLower;
unittest
{
// text
static assert(text("a", 1) == "a1");
// toLower
static assert("AbCdE".toLower() == "abcde");
}
unittest
{
struct H
{
// 型名 H に . 以降の文字列を連結
static string opDispatch(string s)() @property
{
return typeof(this).stringof~s;
}
}
static assert(H.e == "He");
}
unittest
{
struct D {string msg;}
struct H
{
// 型名 H に . 以降の文字列を連結したのを D 型にする
static D opDispatch(string s)() @property
{
return D(typeof(this).stringof~s);
}
}
static assert(H.e == D("He"));
}
unittest
{
struct D
{
string msg;
// . 以降の文字列を連結
D opDispatch(string s)() @property
{
return typeof(return)(text(msg, s));
}
}
struct H
{
static D opDispatch(string s)() @property { return D(typeof(this).stringof~s); }
}
static assert(H.e.l == D("He").l);
static assert(D("He").l == D("Hel"));
static assert(H.e.l.l.o.w.o.r.l.d == D("Helloworld"));
}
import std.algorithm, std.range;
unittest
{
/+
(a, b)=>a.equal(b))(
msg.retro().cycle().take(2),
msg.chain(s).retro().take(2).array().retro())
+/
// msgの最後2文字の逆順を得る
auto left(string msg, string s)
{
return msg.retro().cycle().take(2);
}
static assert(equal(left("He","l"), "eH"));
static assert(equal(left("Hel","l"), "le"));
static assert(equal(left("Hell","o"), "ll"));
static assert(equal(left("Hello","w"), "ol"));
static assert(equal(left("Hellow","o"), "wo"));
static assert(equal(left("Hellowo","r"), "ow"));
static assert(equal(left("Hellowor","l"), "ro"));
static assert(equal(left("Helloworl","d"), "lr"));
// msgとsを連結したものの最後2文字を得る
auto right(string msg, string s)
{
return msg.chain(s).retro().take(2).array().retro();
}
static assert(equal(right("He","l"), "el"));
static assert(equal(right("Hel","l"), "ll"));
static assert(equal(right("Hell","o"), "lo"));
static assert(equal(right("Hello","w"), "ow"));
static assert(equal(right("Hellow","o"), "wo"));
static assert(equal(right("Hellowo","r"), "or"));
static assert(equal(right("Hellowor","l"), "rl"));
static assert(equal(right("Helloworl","d"), "ld"));
// 要するに msgとsを連結した最後の3文字が回文になっているかを判定
bool test(string msg, string s)
{
return equal(left(msg,s), right(msg,s));
}
static assert(!test("He","l"));
static assert(!test("Hel","l"));
static assert(!test("Hell","o"));
static assert(!test("Hello","w"));
static assert( test("Hellow","o")); // <<=========
static assert(!test("Hellowo","r"));
static assert(!test("Hellowor","l"));
static assert(!test("Helloworl","d"));
}
import std.array, std.algorithm, std.range;
unittest
{
/+
((a, b)=>(
a.insertInPlace(msg.countUntil(b)+1, ", "), a.idup)
)(msg.dup, msg.retro().take(2).array().retro())~s
+/
// msgのコピー(編集可能)を返す
auto left(string msg, string s)
{
return msg.dup;
}
static assert(left("Hellow", "o") == "Hellow");
// msgの最後2つを得る
auto right(string msg, string s)
{
return msg.retro().take(2).array().retro();
}
static assert(right("Hellow", "o").equal("ow"));
// aの中からbを見つけてその箇所に", "を挿入
string test(R)(char[] a, R b)
{
a.insertInPlace(a.countUntil(b)+1, ", ");
return a.idup;
}
static assert(test(left("Hellow", "o"), right("Hellow", "o")) == "Hello, w");
}
import std.string, std.range, std.algorithm, std.conv, std.array;
unittest
{
struct D
{
string msg;
// まとめると
D opDispatch(string s)() @property
{
return typeof(return)(
((a, b)=>a.equal(b))(
msg.retro().cycle().take(2),
msg.chain(s).retro().take(2).array().retro())
? ((a, b)=>(
a.insertInPlace(msg.countUntil(b)+1, ", "), a.idup)
)(msg.dup, msg.retro().take(2).array().retro())~s
: text(msg,s));
}
}
struct H
{
static D opDispatch(string s)() @property { return D(typeof(this).stringof~s); }
}
static assert(H.e.l.l.o. w.o.r.l.d == D("Hello, world"));
}
import std.string, std.range, std.algorithm, std.conv, std.array;
unittest
{
struct D
{
string msg;
// 最後のdだけ関数を別途用意して "d! D" を連結させる
string d(T)() @property
{
return text(msg, T.stringof.toLower(), "! ", T.stringof);
}
}
static assert(D("Hello, worl").d!D == "Hello, world! D");
}
まとめ
組み合わせると
import std.string, std.range, std.algorithm, std.conv, std.array;
struct D
{
string msg;
D opDispatch(string s)() @property
{
return typeof(return)(
((a, b)=>a.equal(b))(
msg.retro().cycle().take(2),
msg.chain(s).retro().take(2).array().retro())
? ((a, b)=>(
a.insertInPlace(msg.countUntil(b)+1, ", "), a.idup)
)(msg.dup, msg.retro().take(2).array().retro())~s
: text(msg,s));
}
string d(T)() @property
{
return text(msg, T.stringof.toLower(), "! ", T.stringof);
}
}
struct H
{
static D opDispatch(string s)() @property { return D(typeof(this).stringof~s); }
}
pragma(msg, H.e.l.l.o. w.o.r.l.d! D);
void main() {}
つまり
ここまで書いた処理
_人人人人人人人人人人人人人人人人人人人_
> 全部コンパイル時に評価可能!!!! <
 ̄^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
お後がよろしいようで
お次は4日目 @__DaLong です。