[Prev]    [ Up ]    [Next]

let, let*, letrec

関数内において,何度も繰り返し使うような式があったとき,それが現われるた びに逐一計算するのは効率的ではない.計算の途中結果をいったん局所変数に格 納しておけば,それを再び利用するときには,その局所変数の値を参照するだけ でよいことになる.let, let*, letrecは,局所変数(局所関数)を定義するため の式である.

let

let式の構造は以下の通り.

	(let ((変数1 初期値1)
	      (変数2 初期値2)
	      :
	      (変数n 初期値n))
	  式1
	  式2
	   :
	  式m)

まず初期値1...初期値nが順番に評価された後,それぞれの評価値が変数1...変 数nに代入される.これらの変数を用いて,式1...式mが順に評価される.なお変 数1...変数nのスコープは,let式内部の 式1...式mである.

	(define (dist x1 y1 x2 y2)
	  (let ((dx (- x1 x2))
		(dy (- y1 y2)))
	    (sqrt (+ (* dx dx) (* dy dy)))))
let式の中で再びlet式を用いることもできる(let*,letrecでも同様).
	> (define (M x)
	    (* (let ((x (* x x)))
	         (+ (let ((x (* x x)))
		      x)
		    x))
	       (+ x 1)))
	M
	> (M 2)
	60
それぞれのxのスコープに注意すること. Mの引数xで表現すれば,関数Mの返り値は(x^4+x^2)*(x+1)である.

let*

let*式は,let式と全く同様の構造を持つが,let*の場合はまず初期値1が評価さ れると,直ちにその評価値が変数1に代入される.次に初期値2が評価され,変数 2に代入されるというように,逐次的に代入が行われる.なお変数iのスコープは, すぐあとの代入式(変数(i+1) 初期値(i+1))以降のlet*式の内部全てである.つ まり初期値(i+1)...初期値nの式には,変数1...変数iを使うことができる.

	;; f(x,y) = 1 + (x-y) + (x-y)^2 + (x-y)^3 + (x-y)^4
	(define (f x y)
	  (let* ((d (- x y))
		 (d2 (* d d)))
	    (+ 1 d d2 (* d d2) (* d2 d2))))

letrec

再帰的な局所関数を定義するための式である.letrecを使うには,lambda式再帰呼出し の概念が必要である.

	(letrec ((関数名1 ラムダ式1)
	         (関数名2 ラムダ式2)
	         :
	         (関数名n ラムダ式n))
	  式1
	  式2
	   :
	  式m)
ラムダ式kで記述された関数kが関数名k(要するに変数)に対応づけられる. ここで,ラムダ式で記述された各関数のスコープ(関数が呼び出せる範囲)は,関 数定義部も含めたletrec式全体である.すなわち関数kは,letrec内部の式1... 式mだけでなく,letrec式内で定義されている全ての関数1...関数nでも利用でき る.
	;; 数値リストの各要素を2倍する
	> (define (double-list x)
	    (letrec ((dlist-iter
		      (lambda (p q)
		        (if (null? p)
			    q
			    (dlist-iter (cdr p) (append q (list (* 2 (car p)))))))))
		    (dlist-iter x '())))
	double-all
	> (double-all '(1 2 3))
	(2 4 6)

letとdefine

defineを用いても,局所変数・局所関数を定義することは可能である. しかし例えば,ある関数f内でdefineを用いた場合,定義された変数・関 数のスコープは,その関数fの内部全体にな る.それに対して,letを用いた場合は,定義した変数・関数のスコープをその let式の内部に限定することができる.つまりletの方がより細かく局所変数・局 所関数のスコープを制御することが可能である.

	> (define (f x)
	    (+ x (let ((x (+ x 3))) (* x x))))
	f
	> (f 1)
	;; (+ 1 (let ((x 4)) (* x x)))
	;; (+ 1 (* 4 4))
	17
	
	> (define (f x)
	    (+ (let ((x 4)
	             (y (+ x 1)))
	        (* x y)) x))
	f
	> (f 1)
	9
	> (define (f x)
	    (+ (let* ((x 4)
	              (y (+ x 1)))
	        (* x y)) x))
	f
	> (f 1)
	21
	> (define (f x)
	    (define x 4)
	    (define y (+ x 1))
	    (+ (* x y) x))
	f
	> (f 1)
	24


[Prev]    [ Up ]    [Next]