第6回 Goでドメイン特化言語も作成可能!?
赤坂 けい
チームWordProgress
2010/4/19
Cよりはるかにお気軽なGo。クロージャーや無名関数、インターフェイスによる動的結合を使いこなせば内部DSL作成にも使えるかもしれない。
GoでDSL(ドメイン特化言語)?
昨年秋の登場から、Goのメーリングリスト(リンク)では活発な議論が続けられている(2010年3月時点で、累積投稿数は10,000件を超え、メンバー数も3000人超)。近時の投稿を見ると、Genericの導入やオブジェクト指向など言語仕様の議論に加えて、C言語との連携手法、モバイルサポートなど、実際の活用を意識した質問も多く寄せられている。
そうした議論の中で、『GoはDSL(ドメイン特化言語)の構築に適しているのか(Is Go suitable for building DSL?)』という問いかけ(リンク)に始まる一連の議論が興味深い。
DSLとは、Domain-Specific Language(ドメイン特化言語)の略記であり、特定のタスク専用に設計されたプログラミング言語を意味する。DSLにはプログラミング言語とは独立のもの(例:データベース向けの言語SQL)とプログラミング言語内に埋め込まれるもの(例:ブラウザのDOM操作に特化したJQueryライブラリ。JavaScript内で使用する)とがある。前者を言語外DSL、後者を言語内DSLなどと呼ぶ。ここでの議論は、Goの言語内におけるDSLのものだ。
投稿者のAndrea Fazzi氏は、GoとRubyと比較したブログ投稿(リンク)を行っている。メーリングリストのスレッドでも指摘されている通り、高速なコンパイルのために言語仕様をシンプルに保っているGoは、Rubyと比べたのでは、言語内DSL構築能力という点ではやや厳しいものがあろう(Rubyは、Ruby流のやり方に十分に慣れた人が便利と感じるであろう(*1)、柔軟な表現を許容している)。
[*1]参考 まつもとゆきひろ氏談より [ 出典]
Railsをはじめ、さまざまな言語内DSLを可能にしているRubyは、初心者ではなく生産性を追求する怠惰(lazy)なプログラマにフォーカスを当てているという旨を、作者のまつもと氏は一貫して主張しているものと思われる。なお、まつもと氏自身は、Goをすべてがオブジェクトである静的言語と理解し、高く評価している(Rubyの記述に用いているC言語から乗り換えようと思った始めての言語であるとのこと)。
とはいえ、Goはクロージャと無名関数を扱える。また、静的型付言語であるが、型表記を省略する仕組みがあり、インターフェイスにより動的結合が可能となっている。これらの機能の表現はC言語よりJavaScriptに近く、GoによるDSL構築のポテンシャルは、JavaScriptに近いのではと期待している。Railsのような言語内DSLが作れるかはさておき、Goでも相当な言語内DSLを構築できそうではある(もちろん、C言語と同じく、別途の言語を作ることを意味する言語外DSLを記述することもできる)。
以下は、先のスレッドにおいて例示されている、Goで記述されたDSLの試験的なコード(タスク記述DSL)である。どこかJavaScriptテイストなDSLに見えるのではないだろうか?
func main() { var hello = task( Action(func() { println("Hello") })) var world = task( Action(func() { println("World!") }), DependsOn(hello)) var bye = task( Action(func() { println("Bye!") }), DependsOn(hello, world)) bye.Run() }
これは、以下のように書き換えた方が読みやすいかもしれない。
func main() { _h :=func() { println("Hello") } hello := task(Action(_h)) _w :=func() { println("World!") } world := task( Action(_w), DependsOn(hello)) _b := func() { println("Bye!") } bye := task( Action(_b),DependsOn(hello, world)) bye.Run() }
実行結果は以下の通りとなる。
Hello World! Bye!
上記の変数_h、_w、_bには、引数・戻り値のない関数を代入できる。もう少し手間をかけて、引数・戻り値のある関数をタスクとして記述できるようになると、DSLとしての実用度が増すことだろう。
このタスク記述DSLの実装では、インターフェイスが活用されている。サンプルということもありコードも短いので、興味のある方は、コードを見ておいてほしい(現状のコードを動作させるためには、セミコロン推論の仕組みなどが導入された後のビルド版(Linux、Macのもの)を用いる必要があることに注意)。
それでは、今回は、Goのコレクション機能(集合を扱う機能)であるmapを学び、インターフェイスとともに学んでいきたい。
1/3 |
![]() |
Index | |
Goでドメイン特化言語も作成可能? | |
![]() |
Page1 GoでDSL(ドメイン特化言語)? |
Page2 Goの組込コレクション機能mapを学ぶ | |
Page3 任意の型を格納可能なinterface{} おわりに |
Coding Edgeお勧め記事 |
![]() |
いまさらアルゴリズムを学ぶ意味 コーディングに役立つ! アルゴリズムの基本(1) コンピュータに「3の倍数と3の付く数字」を判断させるにはどうしたらいいか。発想力を鍛えよう |
![]() |
Zope 3の魅力に迫る Zope 3とは何ぞや?(1) Pythonで書かれたWebアプリケーションフレームワーク「Zope 3」。ほかのソフトウェアとは一体何が違っているのか? |
![]() |
貧弱環境プログラミングのススメ 柴田 淳のコーディング天国 高性能なIT機器に囲まれた環境でコンピュータの動作原理に触れることは可能だろうか。貧弱なPC上にビットマップの直線をどうやって引く? |
![]() |
Haskellプログラミングの楽しみ方 のんびりHaskell(1) 関数型言語に分類されるHaskell。C言語などの手続き型言語とまったく異なるプログラミングの世界に踏み出してみよう |
![]() |
ちょっと変わったLisp入門 Gaucheでメタプログラミング(1) Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう |

- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
![]() |
|
|
|
![]() |