変数のスコープ --- 局所変数・大域変数
関数の定義
> (define (succ x) (+ x 1)) succの引数(パラメータ)に使われる変数xは、その関数の内部でのみ有効である. このような変数を局所変数という.
> (succ 3)によって、関数が呼び出されると、局所変数xに3が割当てられる. その後,本体(+ x 1)が,このxの値を使って評価される. この局所変数は,関数が評価される際に一時的に用意されるものであって,関数の評価が終わった後にその値を参照することはできない.
> (succ 3) 4 x > x ==> error ;; xは定義されていないこの関数succとは別に
> (define (pred x) (- x 1))が定義されていたとしても,関数pred内の局所変数xと関数succの局所変数xは無関係である.
;; (x - 1)(x + 1) > (define (foo x) (* (pred x) (succ x)) foo > (foo 5) ;; (* (pred 5) (succ 5)) ;; (* (- 5 1) (succ 5)) ;; (* 4 (+ 5 1)) ;; (* 4 6) 24
一方,Scheme処理系のプロンプトから直接に
> (define x 100) xのように定義した場合,この定義は,いつでも参照可能である.このような変数を大域変数という.
> x 100 > (define (f y) (* x y)) f > (f 2) 200 > (set! x -200) -200 > (f 2) -400
ある変数が参照できる範囲をその変数のスコープという. 関数の引数のスコープは,その関数の中のみである. 大域変数は,常に有効であり,そのスコープは全域である. ある大域変数と同じ名前の局所変数があったとき,局所変数のスコープの範囲においては,局所変数の値が有効になる. 局所変数のスコープを抜けた後は,大域変数が有効になる. 大域変数の値は,局所変数の値には影響されない.
> (define (bar x) (set! x (succ x)) x) bar > (define x 100) x > (bar 4) 5 > x 100 > (set! x (bar x)) 101 > x 101また関数のパラメータ以外でも,defineを用いて局所変数を定義することができる.
> (define (f x) (define y (* x x)) (+ 1 x y)) > (f 2) 7
局所関数
> (define (f x y) (define (g z) (* 2 z)) (+ (g x) (g y)))ここで,関数fの内部で定義されている関数gは局所関数であり,関数fの中でのみ有効となる.
> (define (g i) ;; 大域関数g (+ i 2)) > (f 1 2) ;; この中では,局所関数gが有効 6
このようにdefineを用いて,局所変数・局所関数を定義することはできるが,一般的にはlet,let*,letrecといった式を用いる. これは,let式などの方がより柔軟にスコープを制御できるためである.