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