Schemeの評価順序

Schemeは括弧の中を先に計算するのかと思っていたが、どうやら違う。Schemeの評価順序を調べてみた。

実験

まずはC言語で。

int i = 1;
printf("%d", i + ((i = 5), 2)); // 7

絶対使わなそうな書き方だけど、C言語では括弧の中が先に評価されるから、括弧の中で代入文を使うとiの値は5に変わる。i + 2をすると答えは7だ。


次にSchemeを見てみる。

(define i 1)
(define (test1)
  (+ i (begin (set! i 5) 2)))
(test1) ; 3
(test1) ; 7

1回目の評価と、2回目の評価の結果が違う。


代入の順番を変えると、

(define i 1)
(define (test2)
  (+ (begin (set! i 5) 2) i))
(test2) ; 7

答えは常に7。

ということは・・・

(+ i (begin (set! i 5) 2))の場合、

  • iに1を代入
    • (+ 1 (begin (set i 5) 2))
  • iの値を変更
    • (+ 1 (begin 2))
  • beginを評価
    • (+ 1 2)
  • +を評価
    • 3

となっているようだ。

つまり、Schemeの評価順序は

「括弧を先に評価」ではなく、「プログラムのツリーを巡りながら評価」している。

あああああああああああああああああ

そうか!!わかった!!

  • C言語のスタックは今まで評価した内容。
  • Schemeのスタックはこれから評価する内容。

スタックの内容がまるで逆

C言語はスタックに変数の内容を溜め込む。

a = 1;
b = 3;
c = 5;

Schemeはスタックに今まで巡ってきた評価の履歴を溜め込む。

(+ 1 (+ 2 (+ 3 (call/cc) a) b) c)
|<---  履歴  -->|

要するに全然違う内容をスタックに溜め込んでる。


スタック=変数みたいな感じなので、別の命名を考えた。これこそが継続


継続の謎が解けた!!!!!!!!!!!


しまった。継続はもうちょっと後でとか言ってた気がする。

もうちょっと・・・

(set! op +)とやると、処理系によって動作が異なるようだ。

面白いのでお試しアレ。