Previous | ToC | Next |
Ruby のような動的言語を使うことの大きなメリットは、メタプログラミング を容易にすることでしょう。実行時にデータからモジュールやクラスを新しく 生成して、それらを元々あったクラスと同じように使えるため、汎用 的なコードを書きやすく、無駄な繰り返しを避けることができます。
とはいえ、Ruby はインタプリタ言語であることによる実行速度のペナルティが 大きく、また動的であることの結果として、様々なエラーが実行時にしか検出できないという問題があります。
とはいえ、そういうわけで、実行時にクラスの追加とかはできません。
s =<<-EOF some text ... ... EOF eval(foo(s))みたいなコードを書けばすむところです。
Crystal にはもちろん eval はないので、こんなことはできません。が、 これに相当することを実現することができるコンパイル時マクロ機能が あります。以下は、文字列リテラルで与えたコードがコンパイル時にそのまま 評価される例です。
macro echo(s) {{ run("./echo", s)}} end echo( <<-END class Test property a def initialize(@a : Int32) end def pp p @a end end END ) x= Test.new(1) p x.a x.a=2 x.ppこれは、 echo というマクロが、 echo.cr という Crystal プログラムを 与 えられた引数を実行時コマンドライン引数として実行した結果のコードになる、 というもので、 echo を呼ぶ時に class 定義をここではそのまま文字列で 与えています。
echo.cr の中身は
print ARGV[0]だけで、ここでは引数をそのまま出力するだけです。なので、このプログラム 自体は、
class Test property a def initialize(@a : Int32) end def pp p @a end end x= Test.new(1) p x.a x.a=2 x.ppというプログラムと同じで何の芸もありません。が、echo.cr をもっと複雑な 処理をするものに置き換えれば、コンパイル時に任意の文字列を好きなように 処理して生成したソースコード(少なくともクラス定義)を取り込めるわけです。 もちろん、ファイル名をマクロに渡すこともできるので、何かファイルの中身 を加工してできるテキストをソースコードとして解釈することもできます。
まあその、何がしたいかというと、昔 Ruby で書いた N 体計算用諸々を大体 Crystal で動くようにしてさらに FDPS も使えるようにしたいわけです。
FDPS を使うには少なくとも現状では C++ の(ほぼダミーの)メインプログラムから Crystal の本体プログラムを呼べる必要があります。現在の Crystal のドキュメントには どうすればできるかあんまり書いてない気がしますが、とりあえずできたので まあ、、、というところです。
Previous | ToC | Next |