--- title: メンバ転送で内部DSLをつくる tags: dlang author: woxtu slide: false ---  やっはろー。もう日付は過ぎていますけど、飛び入りで参加します。  Ruby の `method_missing` や Scala の `applyDinamic` のように、D言語でも `opDispatch` を定義することで存在しないメソッドを呼んだときの動作をフックすることができます。 ```d import std.stdio, std.string; struct Foo { string opDispatch(string name)() const { return ["Call", name, "!"].join(" "); } string opDispatch(string name)(string arg) const { return ["Call", name, "with", arg, "!"].join(" "); } } void main() { auto foo = new Foo(); writeln(foo.bar()); // Call bar ! writeln(foo.baz("qux")); // Call baz with qux ! } ``` テンプレートの第一引数にメソッド名を取る他は普通のメソッドと同じです。  これを利用して、XML を出力する内部 DSL を書いてみました。 ```d import std.algorithm, std.ascii, std.range, std.regex, std.string; struct XMLGenerator { struct XMLElement { string elem; string[string] attr; string text; XMLElement[] children; string toString(int level = 0) const { auto indent = " ".repeat(level).join; auto attribute = (attr.length)? " " ~ attr.keys.map!(k => k ~ `="` ~ attr[k] ~ `"`).join(" "): ""; return [ indent ~ "<" ~ elem ~ attribute ~ ">", (text.length)? indent ~ " " ~ text: null, children.map!(x => x.toString(level + 1)).join(newline), indent ~ "" ].filter!(x => x).join(newline); } } alias E = XMLElement; static E opDispatch(string elem)(E[] children) const { return XMLGenerator.opDispatch!elem(null, null, children); } static E opDispatch(string elem)(string text, E[] children = null) const { return XMLGenerator.opDispatch!elem(null, text, children); } static E opDispatch(string elem)(string[string] attribute = null, string text = null, E[] children = null) const { return E(elem.replaceAll(regex("^_"), ""), attribute, text, children); } } ``` こんな感じで使います。 ```d import std.stdio; void main() { alias XML = XMLGenerator; writeln( XML.html([ XML.head([ XML.title("D Programming Language") ]), XML._body([ XML.h1([ XML.font(["color": "#ff0000"], "D "), XML.span("Programming Language") ]), XML.b("Hello world!") ]) ]) ); } ``` ```html D Programming Language

D Programming Language

Hello world! ``` `mixin` と組み合わせたら化けそうです。お粗末さまでした。 > [Operator Overloading - D Programming Language](http://dlang.org/operatoroverloading.html#Dispatch)