Scalaの勉強をはじめたので、とりあえず簡単なパーサーを作ってみてます。
http://d.hatena.ne.jp/nowokay/20111109#1320815540
前回でレキシカルスコープとクロージャを導入しました。
http://d.hatena.ne.jp/nowokay/20111115#1321333375
ときたら、関数リテラルを使いたくなります。
やりましょう。
「{引数 => 処理}」という形で関数が書けるように構文を定義します。
//funcLiteral ::= "{" [[ident {"," ident}] "=>"] lines "}" def funcLiteral: Parser[AST] = "{"~>opt(repsep(ident, ",")<~"=>")~lines<~"}"^^{ case p~x => { p match{ case Some(param) => Func(param.map(_.name), x) case None => x } } }
「=>」が来たら関数リテラルで、こなかったらブロックということにしてます。
これはfactorとして扱えるようにしましょう。
//factor ::= intLiteral | stringLiteral | "(" expr ")" |funcLiteral def factor: Parser[AST] = intLiteral | stringLiteral | ident | "("~>expr<~")" | funcLiteral
あとは、構文処理のときにその時点での環境と一緒にクロージャとしてまとめます。
case f:Func =>{
Closure(env, f)
}
そしたら、こういう感じで関数を扱えるようになります。
val fl = {x => x + 10}; println(fl(3));
もちろん関数をそのまま実行させることもできます。
println({x, y => x * y}(3, 4));
あと、こういう感じで2パラメータの関数のカリー化もできてます。
def high(x) ={y => x * y}; val m3 = high(3); val m4 = high(4); println(m3(5)); println(m4(5));
というか、この子かわいい!
なんかできる子になってる!
そうすると、次のようにfor文も書けます。
def for(start, end, proc)={ def impl(i)={ if(i < end + 1){ proc(i); impl(i + 1) }else{ 0 } }; impl(start) }; for(2, 5, {i => println(i); println(i * 2) });
なんか、実行サンプルがまともなプログラムになってきました!
データ構造がない気もしますが、大丈夫。
def array3(x, y, z) = {idx => if(idx < 1) x else if(idx < 2) y else z }; val ar = array3(11, 13, 17); println(ar(2) + ":" + ar(1) + ":" + ar(0));
こんな感じで、3要素の配列が定義できちゃいます!
できる子ですから!
あとは適当に組み合わせれば、どんなデータ構造も実現できるってわけです。
ソースはこれです。
https://gist.github.com/1345875/7cc5b01c802f43d0a1482c720792566d9ab91ec9