本日は私、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 です。