julia入門で多段階計算
名前だけ知っていた Julia 言語をなんとなく触ってみました。(グラフ(図の方ね)を書く手段を探してたというそれらしい理由もある)
#今回使用したのは Julia 0.3.1 mingw32版 です。
Juliaはそれ自身で項を操作でき、任意の式からその項を生成することが出来ます。
この機能を使えば、項を評価して段階的に項を生成していくような計算(多段階計算/MultiStageProgramming)が実現できそうです。
以下に多段階計算*1の(紹介で)よく在る例を書いてみました。(グラフどこ逝った
基本文法
必要な内容だけ導入しておきます。あとは勘でヨロシク…(^^;;
用語はJuliaとして正しくないかもしれないので注意。
- x -> e
- ラムダ式
- eval(e)
- 式 e を評価
- :e
- 式 e の項。 #例えば :(1+2) は :3 ではなく :(1+2) になる。
- :->
- ラムダ式のコンストラクタ
- :call
- 関数適用のコンストラクタ
- Expr(e, ...)
- 項を構成する関数 # 例えば eval(Expr(:->, :x, :x)) で恒等関数が出来る
今回重要なのは Expr関数 です。
:(コロン) は渡した式がそのまま項として(=未評価のまま)得られますが、Exprは普通の関数と同様に引数が評価されることに注意して下さい。
> :(1+(1+2)) # `>' 以降が入力 :(1 + (1 + 2)) # REPLが返す結果 # `#' 以降がコメント > Expr(:call, :+, 1, 1+2) :(1 + 3)
多段階計算でpowerを計算
この例では、一般的なpower関数から与える引数(指数)毎に特化した項を生成し、そこから関数を作ります。
#プロンプトには型が表示されないのでMLっぽい注釈がコメントに書いてあります。
まず xのy乗 を計算する(コードを生成する)関数を定義。
# (int code) * int -> int code > function mult(x,y) y==0 ? (:(1)) : Expr(:call, :*, x, mult(x, y - 1)) end mult (generic function with 1 method)
cube は任意の式を3回掛けるようなコードを mult から生成します!!
# (int -> int) code > cube = Expr(:->, :y, mult(:y, 3)) :(y->y * (y * (y * 1))) # 3に特化した項が出来た
cube を評価すると、引数を3回掛けるような関数になるはず。2を渡すと(当然)8が得られる。
# eval : 'a code -> 'a > eval(cube) (anonymous function) # int->int の関数のはず > eval(cube)(2) 8 # やった
もう少し一般化
cube を一般化し、任意の値(y)を任意の回数(n)展開する式を生成する関数を定義することも出来ます。
# int -> (int -> int) code > exponent = n -> Expr(:->, :y, mult (:y, n)) (anonymous function)
3 を渡すと、任意の値(y)を3回掛けるような項を生成します。
> exponent(3) :(y->y * (y * (y * 1))) > eval(exponent(3))(2) 8
ダメな例
ついでに(私が初めに書いた(><)) mult のダメな定義の例を挙げておきます。
> function mult(x,y) y==0 ? (:(1)) : :($x * eval(($mult)($x,$y - 1))) end mult (generic function with 1 method) > mult(:x, 3) :(x * eval((mult)(x,3 - 1)))
:(コロン) を使っているため、そこでevalの評価が止まってしまっています。
これだと遠回りに普通の関数のように実行されるだけですね :p
感想
型が無いので生成した項にエラーが無いかはプログラマが保障しないといけません。
特に今回のような項を手で組み上げるケースでは、コード生成までは問題無いのにevalするとエラーになる場合がやっかいです。
まともな多段階計算の処理系なら生成された項の型安全性まで検査できるし、同じことですが、ステージを混同してIntとExprを掛け算したりすることも無くなります(多分)。
やはり型が必要ですね。 (anonymous function)てなんやねんヽ(`Д´)ノ
*1:MSP=MultiStageProgramming