Schemeをつくろう(9) if
さて、構文という奴に取りかかります。あぁ、Schemeには構文がないんだっけ。でもifは構文だよな。マテ、値を返すから式か?・・・構文の定義がイマイチ微妙です。
あんまり細かいことは気にせず進みます。
ifの挙動
ifはdefineと同じように特別な関数です。
通常、Schemeは括弧の中から計算していく訳ですが、ifやdefineは括弧の中を評価するよりも先にやるべき事があります。
> (define l '(1 2 3)) > (if (pair? l) (car l) (cdr l)) 1
実行の順番を整理すると、
- まず、(pair? l)を評価して、#t
- #tだったら、(car l)を評価。
この時、(cdr l)は評価しない。という所がポイント。だからifは特別な関数です。
実装
この考察を元に実装していきます。
#t,#fが無かったので、boolean型を増やしました。
実装はこんな感じ。
/* syntax */ static object if_syntax(object env, object args) { if (length(args) == 3) { object ex = car(args); /* over write ex */ ex = eval(env, ex); env = car(ex); /* split env */ ex = cdr(ex); if (!is_boolean(ex)) error("syntax if : not boolean"); if (is_true(ex)) return eval(env, cadr(args)); else return eval(env, car(cddr(args))); } else error("syntax if : arugument error"); }
リスト処理系を増やしてみました。car,cdrを減らしていかないと。
evalすると、carに環境、cdrに結果が入って返ってきます。多値がホシィ。
てすとぉ
さて、遊んでみます。
input> (define b #f) (define x 5) (if b (+ x 2) (+ x 3)) debug> (define b #f) #f debug> (define x 5) 5 debug> (if b (+ x 2) (+ x 3)) 8
おぉぉぉぉぉ。ifだぁ!!
電卓以上になった!!
ifを搭載したので、電卓以上の機能は備えたつもり。
(足し算しか出来ないけど)
環境問題
またここで環境の問題が・・・ifは環境を返すのかどうか?
debug> (if (define x #t) x y) #t debug> x ERROR : eval : undefind value
ifの中では環境を維持するけど、外には出さないという方針で行きます。
言語デザインって大変なんだなぁと感じる。今日この頃です。