HOME �⤦�ҤȤĤ� Scheme ���� download �񤭹���

17. �ٱ�ɾ��


1. ����

�ٱ�ɾ�� (lazy evaluation) �Ȥϡ��ͤ�ɬ�פˤʤ�ޤǷ׻����ʤ��Ȥ����׻���ˡ�Ǥ��� ������ˡ�������ϥǡ����˷����֤���¤�������Ȥ߹��ळ�Ȥ��Ǥ��� ̵�¤�ʷ��ɽ���Ǥ��뤳�ȤǤ�������ˤ�äơ��ץ������Υ⥸�塼�벽��¥�ʤ��졢 �ץ�����ब�������ʤ�ޤ����ٱ�ɾ���������ˤĤ��Ƥ� �ʤ��ؿ��ץ������Ͻ��פ��򸫤Ƥ���������

����Ū���ٱ�ɾ���������줿����Ȥ��Ƥ� Haskell ��ͭ̾�Ǥ����� Scheme ����ʬŪ���ٱ�ɾ����������Ƥ��ޤ���

2. �ٱ�ɾ���ˤ������ؿ�

R5RS �Ǥ��ٱ�ɾ���ˤ������ؿ��Ȥ��Ƽ��Τ�Τ��Ѱդ���Ƥ��ޤ��� ɾ��ˡ���ؼ�����Ƥ��뤬�ºݤη׻����Ԥ��Ƥ��ʤ���־��֤�ץ��ߥ��Ȥ����� �ץ��ߥ����� (force)���뤳�Ȥ��ͤ��׻�����ޤ���
(delay proc)
proc ��ץ��ߥ��ˤ��ޤ���
(promise? obj)
obj ���ץ��ߥ��ʤ� #t ���֤��ޤ���
(force promise)
promise �����ͤ�׻����ޤ���

3. �ٱ�ɾ���δ�ñ����

�ٱ�ɾ���δ�ñ����� [sample 1] �˵󤲤ޤ������Υ���ץ�Ǥϡ�(+ 1 2) �� delay ��Ĥ��äư��٥ץ��ߥ��ˤ��Ƥ���� force ����Ѥ������ͤ���Ф��Ƥ��ޤ���
[sample 1]
> (define laz (delay (+ 1 2)))
> laz
#<promise:laz>
> (promise? laz)
#t
> (force laz)
3
> (* 10 (force laz))
30
���������դ������Τϥץ��ߥ��� force �ˤ�äƾ��񤵤줺���ץ��ߥ��Τޤޤ��Ȥ������ȤǤ��� �Ĥޤꡢforce �ϥץ��ߥ������ͤ�׻����ޤ������ץ��ߥ��������Ѥϵڤܤ��ޤ��� ���äƥץ��ߥ��ϲ��٤Ǥ�Ȥ��ޤ魯���Ȥ��Ǥ��ޤ���

4. �ٱ�ɾ����Ȥä�̵�¥ꥹ�Ȥ�ɽ��

����Ǥ���®�ٱ�ɾ�������Ѥ���̵�¥ꥹ�Ȥ�ɽ�����ޤ��礦�� �ޤ���̵�¥ꥹ�Ȥ�ɽ�����뤿��δ��ܴؿ�������������줫�餽����Ȥä� �����ɽ�������ޤ������ͷ׻��ؤα��Ѥ򼨤��ޤ���

̵�¥ꥹ�Ȥϡ�

(<val> . <promise>)    (1)
���ͤˡ�car �������ꤷ���ͤǡ�cdr �����ץ��ߥ�����ʤäƤ��륳�󥹥����ɽ���ޤ��� cdr ���Υץ��ߥ��� force ����Ȥޤ���(1) �Τ褦�ʥ��󥹥��뤬��������褦������ҹ�¤�� ��뤳�Ȥˤ�ä�̵�¥ꥹ�Ȥ�ɽ���ޤ��ʿޣ��ˡ����󥹥��������Ҥˤ��ɽ���ϡ��̾�Υꥹ�Ȥ�Ʊ���Ǥ����� cdr ����ץ��ߥ��ˤ��뤳�Ȥˤ�ä��̾�Υꥹ�ȤȤϰۤʤꡢ̵�¥ꥹ�Ȥ�ɽ���Ǥ���褦�ˤʤ�ޤ���


�ޣ����ͤȥץ��ߥ�����ʤ륳�󥹥���ˤ��̵�¥ꥹ�Ȥμ�����

4.1. ̵�¥ꥹ�Ȥ�ɽ�����뤿��δ��ܴؿ��ȥޥ���

[code 1] ��̵�¥ꥹ�Ȥ򰷤�����δؿ��ȥޥ����򼨤��ޤ��� ������ǺǤ���פʤΤ� lazy-map �Ǥ����Ȥä�̵�¥ꥹ�Ȥα黻�򤷤ޤ��� �ޤ��� lazy-cons ��ɾ�����٤餻��Ȥ����ü���� delay ��ޤ�Τǡ� �ޥ�������ˤ���ɬ�פ�����ޤ����ؿ����������ȡ�ɾ�����٤餻���������������Ǥ錄�ä��Ȥ���� ɾ������Ƥ��ޤ��ޤ���

[code 1]

01:     ;;;;; basic functions and a macro
02:     
03:     ;;; car for lazy evaluation
04:     (define lazy-car car)
05:     
06:     ;;; cdr for lazy evaluation
07:     (define (lazy-cdr ls)
08:       (force (cdr ls)))
09:     
10:     ;;; lazy cons
11:     (define-syntax lazy-cons
12:        (syntax-rules ()
13:           ((_ a b) (cons a (delay b)))))
14:     
15:     ;;; lazy map
16:     (define (lazy-map fn . lss)
17:       (if (memq '() lss)
18:           '()
19:         (lazy-cons (apply fn (map lazy-car lss))
20:                    (apply lazy-map fn (map lazy-cdr lss)))))
21:     
22:     ;;; lazy filter
23:     (define (lazy-filter pred ls)
24:       (if (null? ls)
25:           '()
26:         (let ((obj (lazy-car ls)))
27:           (if (pred obj)
28:               (lazy-cons obj  (lazy-filter pred (lazy-cdr ls)))
29:             (lazy-filter pred (lazy-cdr ls))))))
30:     
31:     ;;; returns n-th item of the lazy list
32:     (define (lazy-ref ls n)
33:       (if (= n 0)
34:           (lazy-car ls)
35:         (lazy-ref (lazy-cdr ls) (- n 1))))
36:     
37:     ;;; returns first n items of the ls
38:     (define (head ls n)
39:       (if (= n 0)
40:           '()
41:          (cons (lazy-car ls) (head (lazy-cdr ls) (- n 1)))))

(lazy-car ls)
car ���ϳ��ꤷ���ͤʤΤǡ�(car ls) ��Ʊ���Ǥ���
(lazy-cdr ls)
(cdr ls) �� cdr ���ʥץ��ߥ��ˤ� force ��Ȥä��ͤ���Ф��ޤ���
(lazy-cons a b)
(cons a (delay b)) ��Ÿ�������ޥ����Ǥ��� �ؿ�������ȡ�b �����ɾ������Ƥ��ޤ��Τ� delay �ΰ�̣���ʤ��ʤ�ޤ���
(lazy-map fn . lss)
�ٱ�ɾ���Ѥ� map �Ǥ�����������������ٱ�ɾ���Ѵؿ�����ǺǤ���פʤ�ΤǤ��� ���ꤷ���ͤȡ��ץ��ߥ�����ʤ륳�󥹥�����֤����Ȥ����ܤ��Ƥ���������
(lazy-filter pred ls)
�ٱ�ɾ���Ѥ� filter �Ǥ���̵�¥ꥹ�� ls �Τ��� pred �� #t �ˤʤ��Τ���ʤ� �ꥹ�Ȥ��֤��ޤ���
(lazy-ref ls n)
�ٱ�ɾ���ꥹ�� ls �� n ���ܤ����Ǥ��֤��ޤ���
(head ls n)
�ٱ�ɾ���ꥹ�� ls �κǽ餫�� n ���ܤޤǤ����Ǥ���ʬ�ꥹ�Ȥ��֤��ޤ���

4.2. ̵�¿���

lazy-cons, lazy-map ��Ȥ���̵�¿��󤬴ʷ��ɽ���Ǥ��ޤ��� �����Ǥϡ� ����ˤȤä��������ޤ���

4.2.1. ���ιब���ι�δؿ���ɽ��������

���ιब���ι�δؿ� (f) ��ɽ��������:
ai+1 = f(ai)
�� [code 2] �� (inf-seq a0 f) ��ɽ����ޤ��������ǡ�a0 �Ͻ��ǡ�f �ϼ��ι��׻����뤿��δؿ��Ǥ���

(inf-seq a0 f) �ϺƵ�Ū������ˤʤäƤ��ꡢ ����������顢��ब a0 �裲�ब (f a0) �Ǥ��ꡢ �� n+1 ��� (f an) ��ɽ����뤳�Ȥ��ʷ��ɽ������Ƥ��ޤ��� inf-seq ��Ȥ�������������������Ϥ��줾�� (ari a0 d), (geo a0 r) ���ͤ� ����Ǥ��ޤ��������ǡ�a0, d, r �Ϥ��줾�� ��ࡢ�����������ɽ���ޤ���

[code 2]

01:     ;;;;  sequences
02:     
03:     ;;; infinite sequences represented by a_(n+1) = f(a_n)
04:     (define (inf-seq a0 f)
05:       (lazy-cons a0 (inf-seq (f a0) f)))
06:     
07:     ;;;arithmetic sequence
08:     (define (ari a0 d)
09:       (inf-seq a0 (lambda (x) (+ x d))))
10:     
11:     ;;; geometric sequence
12:     (define (geo a0 r)
13:       (inf-seq a0 (lambda (x) (* x r))))
inf-seq ��̵�¿��󤬤Ǥ��뤳�Ȥ��ǧ���Ƥߤޤ��礦��sample 2�ˡ� geo ��Ȥäƽ�� 1������ 2 ��������� g1 �� ��� 1������ 1/2 ��������� g2 ���ꡢhead ��Ȥäƺǽ�� 10 ���ɽ�������ޤ��������ȿ��󤬤Ǥ��Ƥ��뤳�Ȥ���ǧ����ޤ���
���ˡ�lazy-map ��Ȥä� g1 �� g2 ��ݤ���碌��������ꡢ head �Ǻǽ�� 10 �����Ф��ޤ���1 �� 10 ���¤ӡ������ȷ׻�����Ƥ��뤳�Ȥ��狼��ޤ���

���ˡ���������� lazy-filter �ˤĤ���Ĵ�٤Ƥߤޤ��礦�� �ޤ���(ari 1 1) �ǡ� (1 2 3 ....) �Ȥ������� ar1 �� ���ޤ���head �ǡ��ǽ�� 10 ���ɽ��������� 1 ���� 10 �ޤǤ�ɽ������ޤ����� ����ˡ�lazy-filter ��Ȥäƶ�������Ф����ǽ�� 10 ���ɽ��������� 2 ���� 20 �ޤǤ�ɽ������ޤ���

[sample 2]

> (define g1 (geo 1 2))         ;��� 1 ���� 2 ���������
> (define g2 (geo 1 (/ 1 2)))   ;��� 1 ���� 1/2 ���������
> (head g1 10)
(1 2 4 8 16 32 64 128 256 512)
> (head g2 10)
(1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256 1/512)
> (head (lazy-map * g1 g2) 10)
(1 1 1 1 1 1 1 1 1 1)
> (define ar1 (ari 1 1))        ;��� 1 ���� 1 ����������
> (head ar1 10)
(1 2 3 4 5 6 7 8 9 10)
> (head (lazy-filter even? ar1) 10)
(2 4 6 8 10 12 14 16 18 20)

4.2.2 Fibonacci ����

Fibonacci ����ϡ�
fib(1) = 1
fib(2) = 1
fib(n+1) = fib(n) + fib(n-1)
��ɽ��������Ǥ���lazy-cons �� lazy-map ��Ȥ��ȡ�[code 3] �˼����ͤˡ����ؾ������Τޤޤ� �����ɤ��񤱤ޤ��������� O(n) �Υ��������dzƹब�׻�����ޤ���[sample 3] ���ͤϽֻ��� �׻�����ޤ���

[code 3]

01:     (define fib
02:       (lazy-cons 1
03:                  (lazy-cons 1
04:                             (lazy-map + fib (lazy-cdr fib)))))

[sample 3]
> (head fib 20)
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
> (lazy-ref fib 100)
573147844013817084101

4.3. ̵�¿���ο��ͷ׻��ؤα���

�ʲ������ �ʤ��ؿ��ץ������Ͻ��פ��ˤ��ä���� Scheme ��Ȥäƽ�ľ������ΤǤ��� �ٱ�ɾ���ο��ͷ׻��ؤα��ѤˤĤ��Ƥ� SICP 3.5. Streams �⻲�Ȥ��Ƥ���������

4.3.1. �˥塼�ȥ�-��ץ���ˡ�ˤ��ʿ�����η׻�

�˥塼�ȥ�-��ץ���ˡ�Ͽ��� N ��ʿ������ �������� a0 ����Ϥ�ơ��ʲ��μ���Ȥäƶ�����ɤ����Ƥ�����ˡ�Ǥ���
     a(n+1) =  (a(n) + N/a(n)) / 2                   (2)
�⤷�����ζ��������˸��� a �˼�«����ʤ顢
      a =  (a +  N/a) / 2
�������äơ�
      2a = a +  N/a
      a =  N/a
      a*a = N
      a =  squareroot(N)
�Ȥʤꡢ�Τ��˶˸��� a �� N ��ʿ�����Ǥ��� (2) ����ꡢ�������������δؿ��ʤΤǡ�����ͤο���� inf-seq ��ɽ���ޤ��� ����ͤ� 1 �˸��ꤷ�ޤ����������ο���ϼ�«���ᤤ�Τ�����Ϥ���ޤ���

[code 4] ��ʿ���������ץ������򼨤��ޤ���

[code 4]

01:     ;;; Newton-Raphson method
02:     (define (newton-raphson n)
03:       (inf-seq 1 (lambda (x) (/ (+ x (/ n x)) 2))))
04:     
05:     ;;; returning a reasonable answer.
06:     ;;; If the ratio of successive terms is in (1 - eps) and (1 + eps),
07:     ;;; or the following term is zero,
08:     ;;; the function returns it.
09:     (define (lazylist->answer ls eps)
10:       (let ((e1 (- 1.0 eps))
11:             (e2 (+ 1.0 eps)))
12:         (let loop ((val (lazy-car ls))
13:                    (ls1 (lazy-cdr ls)))
14:           (let ((val2 (lazy-car ls1)))
15:             (if  (or (zero? val2) (< e1 (/ val val2) e2))
16:                 (exact->inexact val2)
17:               (loop val2 (lazy-cdr ls1)))))))
18:     
19:     ;;;
20:     (define (my-sqrt n eps)
21:       (lazylist->answer (newton-raphson n) eps))
(newton-raphson n)
n ��ʿ�����ζ���ͤ��ٱ�ꥹ�Ȥ���ؿ��Ǥ���
(lazylist->answer ls eps)
�ٱ�ꥹ�Ȥ�Ϣ³���룲����椬 (1 - eps) �� (1 + eps) �Ȥδ֤����뤫�� �����ܤιब�����ˤʤ�С����Σ����ܤι���֤��ޤ���
(my-sqrt n eps)
n ��ʿ���������и��� eps �ǵ��ޤ���
> (my-sqrt 9 0.0000001)
3.0

4.3.2. ������ʬ

ñ�����ʬ�μ��� [code 5] �� easydiff ��ɽ����ޤ������μ��� f ����ʬ�����ؿ��� x ����ʬ����� x ���͡� h ����ʬ����뤿��� x ���ͤ����Ǥ���������� h �򥼥��˶�Ť������ʬ���ͤζ�����ɤ��ʤ�ޤ����� ����ԥ塼���ο��ͷ׻���θ����������뤿�� h �򤢤ޤ꾮�����ϤǤ��ޤ���

�����ǡ�lazylist-diff �˼����褦�� ����� h0 ������Ƥ����ͤ�Ⱦʬ�ˤ��Ƥ����ٱ�ꥹ�� (geo h0 0.5) ���ꡢ ������б��������ͤ���ʬ�ꥹ�Ȥ���ޤ���

(lazylist->answer (lazylist-diff h0 f x) eps)
��Ȥä���ľ���ͤ���Ƥ��ɤ��ΤǤ�������«���٤��Τǡ���«���᤯����ؿ� super ��Ȥä� ��«�����ޤ��� ��«������ƥ��˥å��ˤĤ��Ƥ� �ʤ��ؿ��ץ�����ߥ󥰤Ͻ��פ� �򸫤Ƥ��������� ��«���®�����륢�르�ꥺ��Ϥ���ʤ��ʣ���ǡ��̾��ȿ����Ȥä������ǥ��󥰤ǤϤ��ʤ���̤ˤʤ�ޤ��� �ٱ�ɾ����Ȥ��Ȥ��줬�����ؤ�����˶ᤤ���Ǵʷ��ɽ���Ǥ��ޤ����ޤ����ץ�����ब�⥸�塼�벽����Ƥ���Τ� ���Τޤ�¾�������Ŭ���Ǥ��ޤ���4.3.3. ��Ǽ���������ʬ�� [code 5] �Ǽ�������«��®�ؿ��򤽤Τޤ޺����Ѥ��Ƥ��ޤ���

[code 5]

01:     ;;; differentiation
02:     
03:     ;;; primitive function for differentiation
04:     (define (easydiff f x h)
05:       (/ (- (f (+ x h)) (f x)) h))
06:     
07:     ;;; create a lazy list of approximation for differentiation
08:     (define (lazylist-diff h0 f x)
09:       (lazy-map (lambda (h) (easydiff f x h)) (geo h0 0.5)))
10:     
11:     ;;; eliminate error from the approximation
12:     (define (elimerror n ls)
13:       (let ((a (lazy-car ls))
14:             (b (lazy-second ls))
15:             (c (expt 2 n)))   
16:         (lazy-cons
17:          (/ (- (* b c) a) (- c 1))
18:          (elimerror n (lazy-cdr ls)))))
19:     
20:     ;;; estimate `n' in elimerror
21:     (define (order ls)
22:       (let* ((a (lazy-car ls))
23:              (b (lazy-second ls))
24:              (c (lazy-ref ls 2))
25:              (d (- (/ (- a c) (- b c)) 1.0)))
26:         (cond
27:          ((< d 2) 1)
28:          ((<= 2 d 16) (inexact->exact (round (log2 d))))
29:          (else 4))))
30:     
31:     ;;;
32:     (define (log2 x)
33:       (/ (log x) (log 2)))
34:     
35:     ;;; improve convergency of the lazy list of the approximation
36:     (define (improve ls)
37:       (elimerror (order ls) ls))
38:     
39:     ;;; return the second value of the lazy list
40:     (define (lazy-second ls)
41:       (lazy-car (lazy-cdr ls)))
42:     
43:     ;;; further improve the convergency of the list
44:     (define (super ls)
45:       (lazy-map lazy-second (inf-seq ls improve)))
46:                 
47:     
48:     ;;; calculate the differentiation of function `f' at x within error eps
49:     ;;; h0 is initial window width
50:     (define (diff f x h0 eps)
51:       (lazylist->answer (super (lazylist-diff h0 f x)) eps))
> (diff sin 0.0 0.1 0.0000001)
0.9999999999999516
> (diff exp 0.0 0.1 0.000001)
0.9999999991733471

4.3.3. ������ʬ

��«�����뤿��Υƥ��˥å��Ϥ��Τޤ޿�����ʬ�ˤ�Ȥ��ޤ��� �ޤ���easyintegrate �Ǥ����Ӥ������������ޤ��� ������֤������Ƕ��ڤäƶ����夲�Ƥ����ٱ�ꥹ�� lazylist-integrate ��������ޤ��� ���δؿ��ϺƵ��ؿ��ǡ�lazy-map ��Ȥäƴʷ�˽񤯤��Ȥ��Ǥ��ޤ��� �Ǹ�˴ؿ� integrate �ǿ�����ʬ�ξ���Ʊ�ͤ˼�«���®������«�����ͤ��֤��ޤ���

�¹���˼����褦�������ư��ޤ���

[code 6]

01:     ;;; integration
02:     
03:     ;;; primitive integration
04:     (define (easyintegrate f a b)
05:       (* (/ (+ (f a) (f b)) 2) (- b a)))
06:     
07:     ;;; create the lazy list of approximation for integration
08:     (define (lazylist-integrate f a b)
09:       (let ((mid (/ (+ a b) 2)))
10:         (lazy-cons (easyintegrate f a b)
11:                    (lazy-map + (lazylist-integrate f a mid)
12:                                (lazylist-integrate f mid b)))))
13:     
14:     ;;; integrate function `f' in a range of `a' and `b' within error `eps'
15:     (define (integrate f a b eps)
16:       (lazylist->answer (super (lazylist-integrate f a b)) eps))
> (integrate sin 0 pi 0.0000001)
2.000000002272428
> (integrate exp 0 1 0.0000001)
1.7182818277724858
> (- (exp 1) 1)
1.718281828459045

5. ������

�ٱ�ɾ�����Ѥ���ȥǡ�����¤�˷����֤��������Ȥ߹��ळ�Ȥ��Ǥ��ޤ���

�̾�Υץ���������ǤϷ����֤��Ϥ����Ѥι�ʸ��Ȥäƽ�ɬ�פ����ä��Τ� �ץ������Υ⥸�塼�벽�ˤϸ³�������ޤ����������ٱ�ɾ���ꥹ�Ȥ�Ȥ��� �ǡ����˷����֤��׻������Ȥ���������������뤳�Ȥ��Ǥ���Τǡ� �ץ�������ʷ�˽񤯤��Ȥ��Ǥ��ޤ���

�ٱ�ɾ���ˤĤ��Ƥ���˾ܤ����Τꤿ���ͤ� Haskell ��Ϣ�Υڡ����� google ��õ�äƤߤƤ�����������������ä����ۺ� Haskell �Τ��ٶ��⸫�ƤߤƤ���������

���Υڡ����Ǽ����������ɤ� ��Ͽ�ˤĤ��Ƥ����ޤ��Τǵ����������� ����������ɤ���ͷ��ǤߤƤ���������