[Prev]    [ Up ]    [Next]

フォームと評価

Schemeシステムにフォーム(データで表現される式)が与えられると,システムはフォームを「評価」して,その値を返す.

変数が評価されると,その変数の値が返される.

	> (define x -1)
	x
	> x
	-1
関数にその引数を与えて評価すると,まず各引数が評価され,最後に関数の値が返る. 引数が複数あるときの評価の順番は,処理系に依存する.
	> (* (+ 1 2) (+ 3 (* 4 5)))
	;;(* 3 (+ 3 (* 4 5)))
	;;(* 3 (+ 3 20))
	;;(* 3 23)
	69
define(変数,関数の定義), set!(変数への代入)などは関数の形をしているが,その引数の全てが評価されるとは限らない. 例えば,
	> (define x 4)
	> (set! x 5)
において,第一引数にあたる"x"の値は評価されない. この他にこのような特殊なフォームとして,
	and or if cond let lambda do quote
などがある.

リストの第一要素は,常に関数あるいは特殊なフォームとして解釈されるので注意が必要である. 例えば,数値リストを引数として,その要素の総和を返す関数sum-of-listがあったとする. 例えば(1 2 3 4)に対しては,要素の合計10を返して欲しい. ところが,以下のように入力すると,

	> (sum-of-list (1 2 3 4))
	==> error: 1 is not a function
とエラーになってしまう.これは,
	(sum-of-list (1 2 3 4))
という式において引数のリスト(1 2 3 4)が評価される際に,その第一要素の『1』が関数であり,(2 3 4)を引数として呼び出されていると解釈されてしまうためである. これを防ぐには,すぐあとで説明するクォートを用いて引数をそのまま関数に渡すようにする必要がある.
	> (sum-of-list (quote (1 2 3 4)))
	10

ちなみにsum-of-listは,以下のように定義できる. 詳細については,再帰呼出し,およびリスト処理関数を参照のこと.

	(define (sum-of-list l)
	  (if (null? l)
	      0
	      (+ (car l) (sum-of-list (cdr l)))))

記号はクォートしない限り,その記号名に対応する変数,関数,あるいは特殊なフォームとして扱われる. システムに定義されていない記号の値を評価するとエラーとなる.

	> (define abc 1)
	abc
	> abc
	1
	> +
	#<function +>
	> no-such-symbol
	==> error : unbound variable: no-such-symbol

クォート

上で挙げたように,quoteは特殊なフォームの一つであり,

	(quote データ)
は,“データ”をそのまま返す(記号はその印字名で返される).
	> (define x 2)
	x
	> x
	2
	> (quote x)
	x
	> (quote X)
	x
	> (quote (IF (= x 1) Y Z))
	(if (= x 1) y z)
quoteは頻繁に用いられるため,'(シングルクォート)で省略される. すなわち (quote x) = 'x
	> (define y 'x)
	y
	> y
	x
	> '(a b c)
	(a b c)
	> '(+ 1 2 3)
	(+ 1 2 3)
	> ''x
	'x

シングルクォート'は,バッククォート`と間違いやすいので気をつけること. Schemeでは,バッククォートは特殊なフォームquasiquoteの省略記法として用いられるが,本文書ではquasiquoteは扱わないことにする.

eval

evalは,与えられたデータの値を評価する(evaluate)関数である.

	> (eval 100)
	100
	> (define x '(+ 1 2 3))
	x
	> x
	(+ 1 2 3)
	> (eval x)
	6
	> (define y 'x)
	y
	> y
	x
	> (eval y)
	(+ 1 2 3)
	> (eval (eval y))
	6	
	> (define z '(1 2 3 4))
	y
	;; consについては,ここを参照のこと.

	> (eval (cons '+ z)) ;; (+ 1 2 3 4)を評価する
	10
	> (eval (cons '* z)) ;; (* 1 2 3 4)を評価する
	24

多くのScheme処理系では,evalはこのように1引数関数として実装されている. しかし,現在のSchemeの仕様書である 『Revised5Report on the Algorithmic Language Scheme』では, evalが2引数の関数と定義されており,第2引数として環境記述子 (environment-specifier)を与えることになっている.


[Prev]    [ Up ]    [Next]