Edited at
RustDay 2

Rust Advent Calendar 12/2分を20分ででっちあげる

More than 5 years have passed since last update.


勢いで書く

今からコード書くのはさすがにムリなので、過去のコードを引っ張り出して、なんかコメント書く。

整形は後回し。


インタープリターのような

TaPL 3章に出てきた簡易言語のインタープリターというほどのものでもないもの。

値は true, false, 0。操作は succ, pred, iszero, if-then-else。とりあえず、こんな感じの言語。

次のような式だったら、その次のような Rust の式で表わすとして、その Rust の式を評価する。

if iszero pred succ 0

then succ succ succ 0
else pred 0

@If(

@IsZero(@Pred(@Succ(@Zero))),
@Succ(@Succ(@Succ(@Zero))),
@Pred(@Zero)
)

元々このコードは Haskell で書いてて、Rust に書き換えたんだけど、かなり1対1で対応したし、Rust は C っぽい文法を持った関数型プログラミング用の言語だという認識。

enum は Haxe と似た感じで代数的データ型を作るもの。で、match でパターンマッチしてなんやかんや。

ポインターが複数種類あるのは、最初つまづいたし、まだつまづくと思う。

ちなみに、0.8 がもう出てるから 0.7 のときに書いたこのコードはもう動かないかもね。


コード全文

// Rust 0.7

enum Term {
True, False, Zero,
Succ(@Term), Pred(@Term), IsZero(@Term),
If(@Term, @Term, @Term)
}

enum Value {
VTrue, VFalse, NV(@NumberValue)
}

enum NumberValue {
VZero, VSucc(@NumberValue)
}

fn eval(t: &Term) -> @Value {
match *t {
True => @VTrue,
False => @VFalse,
Zero => @NV(@VZero),
If(c, t, f) =>
match eval(c) {
@VTrue => eval(t),
@VFalse => eval(f),
_ => fail!("\"if\"'s conditon is evaluated in non boolean.")
},
Succ(t) =>
match eval(t) {
@NV(nv) => @NV(@VSucc(nv)),
_ => fail!("\"succ n\"'s \"n\" is evaluated in non number.")
},
Pred(t) =>
match eval(t) {
@NV(@VZero) => @NV(@VZero),
@NV(@VSucc(nv)) => @NV(nv),
_ => fail!("\"pred n\"'s \"n\" is evaluated in non number.")
},
IsZero(t) =>
match eval(t) {
@NV(@VZero) => @VTrue,
@NV(@VSucc(_)) => @VFalse,
_ => fail!("\"iszero n\"'s \"n\" is evaluated in non number.")
}
}
}

fn pretty(v: &Value) -> ~str {
match *v {
VTrue => ~"True",
VFalse => ~"False",
NV(nv) => fmt!("%d", num(nv)).clone()
}
}

fn num(nv: &NumberValue) -> int {
match *nv {
VSucc(t) => num(t) + 1,
VZero => 0
}
}

fn main() {
println(fmt!("%s", pretty(eval(@True))));
println(fmt!("%s", pretty(eval(@Succ(@Zero)))));
println(fmt!("%s", pretty(eval(
@If(
@IsZero(@Pred(@Succ(@Zero))),
@Succ(@Succ(@Succ(@Zero))),
@Pred(@Zero)
)
))));
println(fmt!("%s", pretty(eval(
@IsZero(@Pred(@If(@True, @Succ(@Zero), @Zero)))
))));
}

https://gist.github.com/kakkun61/6263240


参考

元にした Haskell のコード。(こっちの方が読みやすい気はしてる)