Кристиан Кеннек - интепретация lisp и scheme - 1994

609
Интерпретация Лиспа и Scheme n if < n 2 1 + - n 1 - n 2 Кристиан Кеннек

Upload: hacker34r3532532523

Post on 20-Oct-2015

85 views

Category:

Documents


1 download

DESCRIPTION

Русский перевод книги - LISP in small Pieces (английский перевод книги Christian Quennec - Les Langages LISP (изданной во Франции на французском языке в 1994 году ), Также на гитхабе проекта доступны исходники книги, и исходники на схеме прилагаемые к саммой книге, и версия EPUB - https://github.com/ilammy/lisp . Книга не смотря на свой почтенный возвраст представляет большой интерес для лисперов (и не только) которые хотя хотят понять что же они делают во время программирования и почему оно работает так, как это сделать лучше или по другому. Книга показывает нам LISP изнутри. В книге содержиться 11 интерпретаторов и 2 компилятора (в байкод и Си). Электронная версия распространяется на условиях свободной лицензии (читайте подробнее на гите книги). Примеры в книге акцентируются на Scheme, но это не составит трудностей для лисперов владеющих любым диалектом, в силу минималистичности схемы.

TRANSCRIPT

  • Scheme

    n

    if

    C (meaning e r))

    1. .

    , ,

    . , , -. , , , ; , .

    - - . , -, .

    Scheme; , . Scheme ( 15), - Meroon. - - .

    - Scheme. , , !

  • 14

    , -

    (Apple Mac SE/30, Sony NEWS 3260, - PC PowerBook) : - , (INRIA), (CNRS).

    , , , . , , , , - , -,- , , ,- , , , - , , , .*

    , , , , , .

    , -

    . , - .

    : , , , . , . , :

    (let ((a (+ b 1)))(let ((f (lambda () a)))

    (foo (f) a) ) )b 3foo cons

    (let ((f (lambda () a))) (foo (f) a))a 4b 3foo consf (lambda () a)

    a 4*Sophie Anglade, Josy Byron, Kathleen Callaway, Jerome Chaillox, Jean-Marie Geffroy,

    Christian Jullien, Jean-Jacques Lacrampe, Michel Lematre, Luc Moreau, Jean-Francois Perrot,Daniel Ribbens, Bernard Serpette, Manuel Serrano, Pierre Weis, Claire N. . .

  • 15

    (foo (f) a)a 4b 3foo consf (lambda () a)

    a 4 (4 . 4)

    Scheme. gensym,

    , - . format pp (pretty-printing). - Scheme.

    - Common Lisp, Dylan, EuLisp, ISLisp, Le_Lisp,1 Scheme . . :

    (defdynamic fooncall ISLisp(lambda (one :rest others)

    (funcall one others) ) )

    , [. . ] . :[. . ]. . [. . 587]

    Scheme Scheme , [AS85],

    [Dyb87], [SF89]. , - Revised revised revised revised revised Report on Scheme, R5RS. [KCR98]

    ; , - .

    Scheme , ,* , , , - , , ( , - Scheme).

    1Le_Lisp INRIA.* , -

    (character), (symbol). . .

  • 16

    : symbol?,char?, string?, pair?, number?, boolean?, vector?, procedure?.

    - , : string-ref, string-set!, vector-ref vector-set!.

    car, cdr, set-car! set-cdr!. car cdr . , -

    cadr. -

    . . #\, : #\Z, #\+, #\space. "", ( ). #t #f -. #(do re mi). -, cons, list, string, make-string, vector, make-vector. string->symbol int->char.

    - : read -, display , newline .

    Scheme . begin -

    ; , (begin (display 1) (display 2) (newline)). . ifthenelse,

    Scheme : (if ). - , Scheme cond case. cond , , , (). - , ( : , #f); -, cond. , else:

    (cond ((eq? x flip) flop)((eq? x flop) flip)(else (list x "neither flip nor flop")) )

    case cond, , . , . , case. , else. case:

  • 17

    (case x((flip) flop)((flip) flip)(else (list x "neither flip nor flop")) )

    lambda. lambda , , - . let, let* letrec ( ). set!. - quote.

    define . , . , - let, , . , :

    (define (rev l)(define nil ())(define (reverse l r)

    (if (pair? l) (reverse (cdr l) (cons (car l) r)) r))(reverse l nil) )

    :

    (define rev(lambda (l)

    (letrec ((reverse (lambda (l r)(if (pair? l) (reverse (cdr l)

    (cons (car l) r))r) )))

    (reverse l ()) ) ) )

    Scheme.

    ( ),

    , :

    http://pagesperso-systeme.lip6.fr/Christian.Queinnec/Books/LiSP-2ndEdition-2006Dec11.tgz

    : [email protected]

  • 18

    , Scheme,

    [AS85, SF89]. , -

    : Common Lisp [Ste90], Dylan [App92b], EuLisp [PE92], ISLisp [ISO94],Le_Lisp [CDD+91], Oaklisp [LP88], Scheme [KCR98], T [RAM84], Talk [ILO94].

    , [BG94].*

    * , Franklyn Turbakand David Gifford with Mark A. Sheldon. Design Concepts in Programming Languages. TheMIT Press, 2008. 1352 p. . .

  • 1

    , - . Scheme, ; Scheme. : ; eval apply; . , - , ,, , - .

    Scheme - - .

    - . Lisp 1.5 [MAE+62], . : [Rib69],[Gre77], [Que82], [Cay83], [Cha80], [SJ93], [Rey72], [Gor75], [SS75], [All78],[McC78b], [Lak80], [Hen80], [BM82], [Cli84], [FW84], [dRS84], [AS85], [R3R86],[Mas86], [Dyb87], [WH89], [Kes88], [LF88], [Dil88], [Kam90].

    , , , , , , - . , [Lak80] , - ; , [BM82], .

    , , . (set-car! set-cdr!), . , - . , , , , , . - , ,

  • 1. 20

    +

    Scheme

    -

    + Scheme

    -

    [Sto77]

    [Gor75]

    [McC78b][Kes88]

    [SJ93]

    [Dyb87][R3R86]

    [MP80][LF88]

    . 1.1. .

    .

    1.1 ( ) ( ) -. : . , - Scheme, -.

    1.1. , -

    . , eval, - , . , , , - .

    , . - , , - ; , , - , .

  • 1. 21

    , - . - , - . , - . , - eval . , , , - .

    ( eval), : .1 , , , , , .

    eval, .

    ( - ), eval. , , eval; - eval, . , , - eval. , , eval, : , - .

    , , .

    , eval , , - - . , [Lie87]. -, eval, , , - .

    - . , eval , - .

    , eval -. , eval

    1, , 150 .

  • 1. 22

    ; - . , eval . , , .

    , eval -. R5RS [CR91b, KCR98]. [. . 325]

    1.2. . -

    , ( let lambda) - . . , -, , , . , , - . , evaluate2 : , :

    (define (evaluate exp env) ... )

    1.3. , -

    , . , - . : ( ), , - , .

    , evaluate - , , . , : , , . - ( , ). evaluate , .

    2 , - Scheme eval. , evaluate. apply invoke. .

  • 1. 23

    (define (evaluate exp env)(if (atom? exp) ; (atom? exp) (not (pair? exp))

    ...(case (car exp)

    ...(else ...) ) ) )

    , , , - . , , :

    (define (evaluate exp env)(if (atom? exp)

    (if (symbol? exp) (lookup exp env) exp)(case (car exp)

    ...(else ...) ) ) )

    lookup ( 32) -, . :

    (lookup ) , -

    . , (lookup exp env) - - :

    ... (lookup (symbol->variable exp) env) ...

    , exp, - , . , symbol->variable3 exp ; () - (). , - , - , - . , -. symbol->variable , - -, : , ; , , symbol->variable .

    , lookup , . - , - , lookup

    3 x->y , - . (y->z(x->y ...)) , (z

  • 1. 24

    . -:

    ... (lookup (variable->key (symbol->variable exp)) env) ...

    , . variable->key symbol->variable, exp.

    ( ) , - - . - . - . [Cha96].

    ? -, - . , "a?b:c" , .

    ( ) , . , , car -, , car? .

    (). , , . , . Scheme - .

    - , , :, . [. . 26] :

    (define (evaluate exp env)(if (atom? exp)

    (cond ((symbol? exp) (lookup exp env))((or (number? exp) (string? exp) (char? exp)

    (boolean? exp) (vector? exp) )exp )

    (else (wrong "Cannot evaluate" exp)) )... ) )

    , . - - , -. wrong4 - . , , -

    4, wrong. 7.9.

  • 1. 25

    . - - "Bus error: coredumped" . - . , - , , , - . [. . 307] , , . , , .

    1.4. -

    : . . , -, ( - , Scheme).

    ( , ; , Scheme call/cc).

    , - . . Scheme - (quote, if, set! lambda), Common Lisp (CLtL2 [Ste90]) , , .

    , - , case-: . -, . : quote, if, begin, set! lambda. ( , .)

    (define (evaluate e env)(if (atom? e)

    (cond ((symbol? e) (lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) ) e)(else (wrong "Cannot evaluate" e)) )

  • 1. 26

    (case (car e)((quote) (cadr e))((if) (if (evaluate (cadr e) env)

    (evaluate (caddr e) env)(evaluate (cadddr e) env) ))

    ((begin) (eprogn (cdr e) env))((set!) (update! (cadr e) env (evaluate (caddr e) env)))((lambda) (make-function (cadr e) (cddr e) env))(else (invoke (evaluate (car e) env)

    (evlis (cdr e) env) )) ) ) )

    , -: , , if 5 . .

    1.4.1.

    quote , - - . , - , , . - , . , - M- [McC60] , S-. , - . , M- [McC78a], S-. quote, .

    , - , , . :

    ... (case (car e)((quote) (cadr e)) ... ) ...

    : -, , 33 33, 6 #(fa do sol) #(fa dosol)? - , - ( ).

    5if . , Scheme Common Lisp if , ; if EuLisp ISLisp ; Le_Lisp , , if, begin.

    6: Scheme #(...) .

  • 1. 27

    . - , #(fa do sol) . , #(fa do sol) - (vector fa do sol), , , , #(fa do sol), (vector fa do sol). [. . 175], , , , .

    1.4.2.

    , if: (), , () (). :

    ... (case (car e)((if) (if (evaluate (cadr e) env)

    (evaluate (caddr e) env)(evaluate (cadddr e) env) )) ... ) ...

    -. , : Scheme ( - ) Scheme ( - ). . - , ( TEX) TEX [Knu84]. -, .

    evaluate . - , . , , - , , :

    ... (case (car e)((if) (if (not (eq? (evaluate (cadr e) env) the-false-value))

    (evaluate (caddr e) env)(evaluate (cadddr e) env) )) ... ) ...

    , the-false-value , . - , , :

    (define the-false-value (cons "false" "boolean"))

    , eq? Scheme , , , , the-false-value.

  • 1. 28

    . , - () NIL. : () ( , ), , N,I L.

    Scheme; IEEE [IEE91].

    Scheme ( () - nil !). , () NIL . Le_Lisp NIL (), (- ||) .

    1.4.3.

    , - . begin... end , Scheme begin; progn prog1, prog2 . . - eprogn.

    ... (case (car e)((begin) (eprogn (cdr e) env)) ... ) ...

    (define (eprogn exps env)(if (pair? exps)

    (if (pair? (cdr exps))(begin (evaluate (car exps) env)

    (eprogn (cdr exps) env) )(evaluate (car exps) env) )

    () ) )

    -. - . , - evaluate eprogn.( . [. . 134])

    , - (begin). . (), - , :3 (/\___/\)? , : nil. , , nil () -, ? (begin) empty-begin, - () 813 [Leb05].

  • 1. 29

    (define (eprogn exps env)(if (pair? exps)

    (if (pair? (cdr exps))(begin (evaluate (car exps) env)

    (eprogn (cdr exps) env) )(evaluate (car exps) env) )

    empty-begin ) )

    (define empty-begin 813)

    , begin - -. Scheme, - (begin); - , . : begin , , . : #, , . , . ( - . [. . 83])

    - ( ). , - - ? . , ; , - - , ; - , . - , , ( ).

    Scheme -, , begin, -, ( display), - ( read), . - . begin . -, :

    (if ) (begin ) lambda 7:

    (begin ) ((lambda (void) ) )7 void . , void

    . gensym, . [. . 1.11]

  • 1. 30

    , Scheme begin , , ( ).

    1.4.4.

    , . . , update!.8 , 163.

    ... (case (car e)((set!) (update! (cadr e) env

    (evaluate (caddr e) env))) ... ) ...

    : -, . , . - . [. . 142] , .

    1.4.5.

    ( Scheme) - lambda, -. - make-function, : , .

    ... (case (car e)((lambda) (make-function (cadr e) (cddr e) env)) ... ) ...

    1.4.6.

    , , - - . , - , , , . :

    8 Scheme , - .

  • 1. 31

    ... (case (car e)(else (invoke (evaluate (car e) env)

    (evlis (cdr e) env) )) ) ...

    evlis - . :

    (define (evlis exps env)(if (pair? exps)

    (cons (evaluate (car exps) env)(evlis (cdr exps) env) )

    () ) )

    invoke, (; , ) ( ) . , invoke apply, . ( 1.6 [. . 34] - .)

    evaluate

    - . - : lookup update!, - , make-function invoke, -. evaluate. , , - ( Lisp1 [. . 51]), . .

    cons, evlis. - , , :

    (define (evlis exps env)(if (pair? exps)

    (let ((argument1 (evaluate (car exps) env)))(cons argument1 (evlis (cdr exps) env)) )

    () ) )

    9 . : - , , .

    9 , let : (let (( 1)) 2) ((lambda() 2) 1).

  • 1. 32

    1.5. . -

    , - -. -, - . .

    , lookup update! :(define (lookup id env)

    (if (pair? env)(if (eq? (caar env) id)

    (cdar env)(lookup id (cdr env)) )

    (wrong "No such binding" id) ) )

    10 , - . wrong, .

    , ,11 - . - , . , -, , .

    , - : , , , , -. : , , - . , . , , , .

    update! , , , : . , , .

    (define (update! id env value)(if (pair? env)

    (if (eq? (caar env) id)(begin (set-cdr! (car env) value)

    value)(update! id (cdr env) value) )

    (wrong "No such binding" id) ) )

    10 (. 24).11 ( -)

    , .

  • 1. 33

    update! , . Scheme - . , - , , , , . :

    1) ( );

    2) ( -, );

    3) , #, - ;

    4) , set-cdr! Scheme.

    . - ; .

    . :

    (define env.init ())

    ( , 1.6, .) , ,

    . extend env variables - values.

    (define (extend env variables values)(cond ((pair? variables)

    (if (pair? values)(cons (cons (car variables) (car values))

    (extend env (cdr variables) (cdr values)) )(wrong "Too few values") ) )

    ((null? variables)(if (null? values)

    env(wrong "Too many values") ) )

    ((symbol? variables) (cons (cons variables values) env)) ) )

    , - , Scheme.12 ,

    12 -, Common Lisp, - &aux, &key, &rest. . - [SJ93].

  • 1. 34

    : (), (- ). - :

    ::= ()| | ( . )

    ,

    . , - ( n-) , - . , : , , .

    1.6. , . -

    , , : . : invoke , - : -, .

    (define (invoke fn args)(if (procedure? fn) (fn args)

    (wrong "Not a function" fn) ) )

    . , - , evaluate., , , - , invoke . , 1.7 1.8.

    , - . - , - . :

    1) ;

    2) , ;

    3) ;

    4) , -, .

  • 1. 35

    , - . , . , - (, ), , .

    , , :

    1) ;

    2) , , ;

    3) , , ;

    4) .13

    Common Lisp , , - .

    Scheme , -. - , .[. . 202] , , - begin, .

    , . (f (set! f ) (set! f )), , - . , , .

    , , , , - . , make-function , evaluate. - , .

    13 -, .

  • 1. 36

    :

    (define (make-function variables body env)(lambda (values)

    (eprogn body (extend env.init variables values)) ) )

    , , . , make-function - K, (lambda (a b) a), - :

    (K 1 2) 1 : -

    , env.init - . car cons.

    , :

    (define (make-function variables body env)(lambda (values)

    (eprogn body (extend env.global variables values)) ) )

    , - . ? , ( )?

    (let ((a 1)) ((lambda (a)(let ((b (+ 2 a))) ((lambda (b)

    (list a b) ) ) (list a b) )(+ 2 a) ) )

    1 )

    , :

    ((lambda (a) ((lambda (b) (list a b)) (+ 2 a))) 1)env.global

    ((lambda (b) (list a b)) (+ 2 a))a 1env.global

    (list a b)b 3env.global

  • 1. 37

    (lambda (b) (list a b)) -, b. . a!

    ( )

    a , - invoke , - . , evaluate invoke; -, d.:

    (define (d.evaluate e env)(if (atom? e) ...

    (case (car e)...((lambda) (d.make-function (cadr e) (cddr e) env))(else (d.invoke (d.evaluate (car e) env)

    (evlis (cdr e) env)env )) ) ) )

    (define (d.invoke fn args env)(if (procedure? fn)

    (fn args env)(wrong "Not a function" fn) ) )

    (define (d.make-function variables body def.env)(lambda (values current.env)

    (eprogn body (extend current.env variables values)) ) )

    , env def.env , current.env .

    , . :

    ((lambda (a) ((lambda (b) (list a b)) (+ 2 a))) 1)env.global

    ((lambda (b) (list a b)) (+ 2 a))a 1env.global

    (list a b)b 3a 1env.global

    : - , .

  • 1. 38

    . - :

    (((lambda (a)(lambda (b) (list a b)) )

    1 )2 )

    (lambda (b) (list a b)) , a - 1, b. , a.

    , , d.make-function - : def.env - current.env . : (). , , - ; . ,14 , -, , . - evaluate invoke, make-function :

    (define (make-function variables body env)(lambda (values)

    (eprogn body (extend env variables values)) ) )

    . , - :

    (((lambda (a) (lambda (b) (list a b))) 1) 2)env.global

    ((lambda (b) (list a b))a 1env.global

    2 )env.global

    (list a b)b 2a 1env.global

    (lambda (b) (list a b)) , - a. , - b, , , a b . , ,

    14 , . . closure 144.

  • 1. 39

    . (closure), .

    , make-function . , . [. . 120] make-function -, .

    1.6.1.

    . -,, . - - , , - . unwind-protect, - .

    -, -15 ( ). , , - , .

    , , - . , TEX [Knu84],Emacs Lisp* [LLSt93], Perl [WS91].

    , . - .

    , , - . , . -, . . , , -, - . , . ., , ,

    15 - - , , - , .

    * Emacs Lisp v. 24 Perl 5, .

  • 1. 40

    , ! - , , . .

    , , - : , -. Scheme ( , - let) : lambda. , . . :

    (define (foo x) (list x y))(define (bar y) (foo 1991))

    y foo16 - y, y bar. y bar foo bar, foo y - . , y 0, :

    (define y 0)(list (bar 100) (foo 3)) ((1991 0) (3 0)) ; (list (bar 100) (foo 3)) ((1991 100) (3 0)) ; , bar , foo

    y, foo , y. bar y, - foo . bar y , y .

    , , - .

    , , : , . : , ( ) ,

    16 foo . [Ray91].

  • 1. 41

    , - , , . - , .[. . 103]

    Scheme . Common Lisp - . EuLisp ISLisp , - . [. . 64]

    . , - - , . , . 60.

    -, lambda [Per79], Lisp 1.0 , , (2 3), (1 3):

    (let ((a 1))((let ((a 2)) (lambda (b) (list a b)))3 ) )

    ( ) - function. lambda- , , . - , . d.evaluate d.invoke, function17 :

    (define (d.evaluate e env)(if (atom? e) ...

    (case (car e)...((function) ; : (function (lambda ))(let* ((f (cadr e))

    (fun (d.make-function (cadr f) (cddr f) env)) )(d.make-closure fun env) ) )

    ((lambda) (d.make-function (cadr e) (cddr e) env))(else (d.invoke (d.evaluate (car e) env)

    (evlis (cdr e) env)env )) ) ) )

    17 , (CLtL1 [Ste84]), lambda , - else cond case. d.evaluate lambda. lambda-, - function .

  • 1. 42

    (define (d.invoke fn args env)(if (procedure? fn)

    (fn args env)(wrong "Not a function" fn) ) )

    (define (d.make-function variables body env)(lambda (values current.env)

    (eprogn body (extend current.env variables values)) ) )

    (define (d.make-closure fun env)(lambda (values current.env)

    (fun values env) ) )

    . function , - . , ( ) : - - , - . , , - , , -. (declare (special x)) Lisp 1.5,Common Lisp, Maclisp , , x .

    -. (referential trans-parency). , , - ( , ). :

    (let ((x (lambda () 1))) (x)) ((let ((x (lambda () 1))) x)) 1 , -

    . , . Scheme - , , - . [. . 3.10] , - , -.

    (lambda (u) (+ u u)) - . - . (lambda (n347) (+ n347 n347)) -18 , (lambda (u) (+ u u)).

    18 - -.

  • 1. 43

    , . - . :

    (define (map fn l) ; mapcar, (if (pair? l)

    (cons (fn (car l)) (map fn (cdr l)))() ) )

    (let ((l (a b c)))(map (lambda (x) (list-ref l x))

    (2 1 0)))

    ( (list-ref n) n- .) Scheme (c b a), -

    (0 0 0)! : l (lambda (x)(list-ref l x)), l map.

    , ., - l. -, , map, . , ? , - Unx-, , , , .

    : , - . 1975 Scheme[SS75] , , - , . Common Lisp , , - , -. . Scheme , ML , - , .

    1.6.2.

    . . - , ( lookup) .19

    19 , , , , , . , -, , , , , [Bak92a].

  • 1. 44

    (deep binding), - .

    , (shallow binding). , , , . , - , ; Cval (value cell). lookup - : , , . , -, , - , . , , - , . ( : [SJ93].)

    , 20 . : ( ) . s., .

    (define (s.make-function variables body env)(lambda (values current.env)

    (let ((old-bindings(map (lambda (var val)

    (let ((old-value (getprop var apval)))(putprop var apval val)(cons var old-value) ) )

    variablesvalues ) ))

    (let ((result (eprogn body current.env)))(for-each (lambda (b) (putprop (car b) apval (cdr b)))

    old-bindings )result ) ) ) )

    (define s.lookup id env(getprop id apval) )

    (define s.update! id env value(putprop id apval value) )

    20 , . [BCSJ86].

  • 1. 45

    Scheme putprop getprop , , , [AS85] put get. [. . 2.6]

    ,21 . -,22 , .

    , env. - make-closure, - ( ). - , . .

    , . -, . [Bak78] rerooting.

    , , - , .

    1.7. , -

    . , - Common Lisp (CLtL1) 700 , Le_Lisp 1500, ZetaLisp 10 000. -, . . , - .-, . [Sla61], - , -, , , ?

    , cons, car . . . .

    21 apval [MAE+62]. [. . 51] P-.

    22 ( P-, property) , . , , , -.

  • 1. 46

    . , .23 - , .[. . 370]

    . - env.init.

    (define env.global env.init)

    (define-syntax definitial(syntax-rules ()

    ((definitial name)(begin (set! env.global (cons (cons name void) env.global))

    name ) )((definitial name value)(begin (set! env.global (cons (cons name value) env.global))

    name ) ) ) )

    (define-syntax defprimitive(syntax-rules ()

    ((defprimitive name value arity)(definitial name

    (lambda (values)(if (= arity (length values))

    (apply value values) ; apply Scheme(wrong "Incorrect arity" (list name values) ) ) ) ) ) ) )

    , Scheme , . , t - , #t . , , the-false-value, .

    (definitial t #t)(definitial f the-false-value)(definitial nil ())

    , : . Scheme #t #f, . :

    1) : #t , , t.

    2) #t , t.

    , (if t 1 2) 2, - : (let ((t #f)) (if t 1 2)).

    23, .

  • 1. 47

    . - t f :

    (define (evaluate e env)(if (atom? e)

    (cond ((eq? e t) #t)((eq? e f) #f)...((symbol? e) (lookup e env))...(else (wrong "Cannot evaluate" exp)) )

    ... ) )

    -. . . - , , . , - - ( - ), . [. . 240]

    (car x) , x, , car - . , , :

    (set! my-global (cons c d)) (c . d)

    (set! my-test (lambda () (car my-global))) #

    (begin (set! car cdr)(set! my-global (cons a b))(my-test) )

    ????? , a b. my-test

    car , a. my-test car, b. - my-test my-global: my-test -, my-global .[. . 77]

    24 -, .

    24 , . .

  • 1. 48

    , 96,037% - .

    (definitial foo)(definitial bar)(definitial fib)(definitial fact)

    , ( , ). . , , apply.25 , - , - defprimitive.

    (defprimitive cons cons 2)(defprimitive car car 1)(defprimitive set-cdr! set-cdr! 2)(defprimitive + + 2)(defprimitive eq? eq? 2)(defprimitive < < 2)

    1.8. : .

    (define (chapter1-scheme)(define (toplevel)

    (display (evaluate (read) env.global))(toplevel) )

    (toplevel) )

    , , , - .

    1.9. ? , evaluate,

    , . evaluate , ,

    25 invoke apply.

  • 1. 49

    . , , , - , . , , evaluate, . :

    : (evaluate (quote ) env.global)

    , ( ), ( -), (evaluate (quote ) env.global) . , evaluate 26 . , :

    (evaluate (quote ) env.global) (evaluate (quote (evaluate (quote ) env.global)) env.global)

    ? , -! , evaluate - . , - , . , , , . -. , , 2001, 2001. . - , .

    1.10. 1.1 evaluate , . - . - , - .

    1.2 evlis -, . , .

    1.3 , extend :26 , let, case,

    define . . evaluate,evlis .

  • 1. 50

    (define (extend env names values)(cons (cons names values) env) )

    lookup update!. .

    1.4 [SS80] , rack. , - , . . s.make-function, s.lookup s.update! .

    1.5 , < ! , . -.

    1.6 list.

    1.7 : call/cc.

    1.8 apply.

    1.9 end, -, .

    1.10 Scheme evaluate. evaluate evaluate, evaluate.

    1.11 begin lambda[. . 29], gensym, . begin , gensym.

    , , -

    , , :

    -papers: [SS78a]; , : [McC78b];

    : [Rey72]; : [MAE+62].

  • 2

    Lisp, 1, 2, . . . ,

    , , . , - , . - . , Lisp1 Lisp2, , - . .

    , , . -: lambda, : - . , . , , , , ; , . -, , [AR88]. Scheme , .

    - ( ) . Lisp 1.5 [MAE+62] -. , , , (APVAL, EXPR MACRO1) - .

    Maclisp , - Common Lisp (CLtL2) [Ste90] - . Common Lisp lambda : ! -. lambda-

    1APVAL, A Permanent VALue, ; EXPR, EXPRession, - ; MACRO .

  • 2. LISP, 1, 2, . . . , 52

    : function.

    , Scheme 1975 - , . ( ) , , -, . . ML, .

    2.1. Lisp1 :

    ( make-function); - , - , . - :

    (define (evaluate e env)(if (atom? e) ...

    (case (car e)...((lambda) (make-function (cadr e) (cddr e) env))(else (invoke (evaluate (car e) env)

    (evlis (cdr e) env) )) ) ) )

    :

    1) lambda , - .

    2) : - evaluate; evlis evaluate .

    Scheme - Lisp1.

    2.2. Lisp2 -

    . - . - . , : evaluate,

  • 2. LISP, 1, 2, . . . , 53

    -, - . evaluate:

    ...(else (invoke (lookup (car e) env)

    (evlis (cdr e) env) )) ...

    , , : . - - . , - . , , , . . - fenv evaluate-application, , . , Lisp2 [SG93].

    (define (f.evaluate e env fenv)(if (atom? e)

    (cond ((symbol? e) (lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) )e )

    (else (wrong "Cannot evaluate" e)) )(case (car e)

    ((quote) (cadr e))((if) (if (f.evaluate (cadr e) env fenv)

    (f.evaluate (caddr e) env fenv)(f.evaluate (cadddr e) env fenv) ))

    ((begin) (f.eprogn (cdr e) env fenv))((set!) (update! (cadr e)

    env(f.evaluate (caddr e) env fenv) ))

    ((lambda) (f.make-function (cadr e) (cddr e) env fenv))(else (evaluate-application (car e)

    (f.evlis (cdr e) env fenv)envfenv )) ) ) )

    evaluate-application, , -. lambda, : env fenv. , env ( ) fenv. , evlis eprogn, fenv:

  • 2. LISP, 1, 2, . . . , 54

    (define (f.evlis exps env fenv)(if (pair? exps)

    (cons (f.evaluate (car exps) env fenv)(f.evlis (cdr exps) env fenv) )

    () ) )

    (define (f.eprogn exps env fenv)(if (pair? exps)

    (if (pair? (cdr exps))(begin (f.evaluate (car exps) env fenv)

    (f.eprogn (cdr exps) env fenv) )(f.evaluate (car exps) env fenv) )

    empty-begin ) )

    , ; (invoke) .

    (define (f.make-function variables body env fenv)(lambda (values)

    (f.eprogn body (extend env variables values) fenv) ) )

    evaluate-application , - . Common Lisp, , lambda-.

    (define (evaluate-application fn args env fenv)(cond ((symbol? fn)

    (invoke (lookup fn fenv) args) )((and (pair? fn) (eq? (car fn) lambda))(f.eprogn (cddr fn)

    (extend env (cadr fn) args)fenv ) )

    (else (wrong "Incorrect functional term" fn)) ) )

    , ? - , lookup, f.evaluate - . , fenv, , . , lambda-. :

    (let ((state-tax 1.186))((lambda (x) (* state-tax x)) (read)) )

    (lambda (x) (* state-tax x)) , .

  • 2. LISP, 1, 2, . . . , 55

    , , Lisp1 - . : Lisp2- , , fenv , , , , : . -, wrong.

    , fenv , invoke, procedure? . , Scheme ( CommonLisp ((lookup fn fenv) args) ). evaluate-application:

    (define (evaluate-application fn args env fenv)(cond ((symbol? fn) ((lookup fn fenv) args))

    ... ) )

    , -. : , .

    , . . (if (+3 4) (* 3 4)). Scheme 3 4 :((if + *) 3 4). , . , . Lisp2 , if-, , , lambda-.

    2.2.1.

    ( ). , -, . , Maclisp, , evaluate-application - , f.evaluate:

    (define (evaluate-application2 fn args env fenv)(cond ((symbol? fn)

    ((lookup fn fenv) args) )((and (pair? fn) (eq? (car fn) lambda))(f.eprogn (cddr fn)

    (extend env (cadr fn) args)fenv ) )

  • 2. LISP, 1, 2, . . . , 56

    (else (evaluate-application2(f.evaluate fn env fenv) args env fenv)) ) )

    :(if (+ 3 4) (* 3 4)) ((if + *) 3 4) , ,

    . , , , ; -, .

    (1789 )

    1789 , evaluate-application2 1789, , 1789 , , f.evaluate, ... 1789! , , f.evaluate. , - :

    (define (evaluate-application3 fn args env fenv)(cond

    ((symbol? fn)(let ((fun (lookup fn fenv)))

    (if fun (fun args)(evaluate-application3 (lookup fn env) args env fenv) ) ) )

    ... ) )

    , , . ! -, foo, . :

    (let ((foo foo))(foo ) )

    , , , evaluate-application ,, . :

    (let ((flip flop)(flop flip) )

    (flip) )

    , 54, .

    2.2.2.

    , , -, ,

  • 2. LISP, 1, 2, . . . , 57

    , . , - -.

    , -, , , , . funcall ( function call). ( ) -. :

    (if (+ 3 4) (* 3 4)) (funcall (if + *) 3 4) ( ) f.evaluate.

    funcall . funcall

    (define (funcall . args)(if (> (length args) 1)

    (invoke (car args) (cdr args))(wrong "Incorrect arity" funcall) ) )

    Lisp2 funcall . , - .

    invoke funcall. , , evaluate-application, . funcall apply: , . , funcall - .

    , . (if + *), . , , + *! CommonLisp : - REPL* !

    funcall , - . , - : evaluate-application ; - . funcall + - . :function. -

    *REPL readevalprint loop, . - toplevel.

  • 2. LISP, 1, 2, . . . , 58

    . - :

    (if (+ 3 4) (* 3 4)) (funcall (if (function +) (function *)) 3 4)

    function - f.evaluate. function - [. . 41] (function (lambda )), - . (function -), - .

    ...((function)(cond ((symbol? (cadr e))

    (lookup (cadr e) fenv) )(else (wrong "Incorrect function" (cadr e))) ) ) ...

    , lambda-, Common Lisp 41. , lambda - . Common Lisp , lambda lambda , function.

    funcall - . , function - -. : funcall function. - .

    , ; . - -. .

    2.2.3. Lisp2 Lisp2, -

    , f.evaluate. - : .

    (define fenv.global ())

  • 2. LISP, 1, 2, . . . , 59

    (define-syntax definitial-function(syntax-rules ()

    ((definitial-function name)(begin (set! fenv.global (cons (cons name void) fenv.global))

    name) )((definitial-function name value)(begin (set! fenv.global (cons (cons name value) fenv.global))

    name) ) ) )

    (define-syntax defprimitive(syntax-rules ()

    ((defprimitive name value arity)(definitial-function name

    (lambda (values)(if (= arity (length values))

    (apply value values)(wrong "Incorrect arity"(list name values) ) ) ) ) ) ) )

    (defprimitive car car 1)(defprimitive cons cons 2)

    :

    (define ( Lisp2 )(define (toplevel)

    (display (f.evaluate (read) env.global fenv.global))(toplevel) )

    (toplevel) )

    2.2.4.

    . ? , , , . - , . , let, . , . - flet (functional let) :

    (flet ((1 1 1)...

    (n n n) )... )

  • 2. LISP, 1, 2, . . . , 60

    flet , - lambda, . flet (lambda i i) - i . , i function, .

    flet f.evaluate :

    ...((flet)(f.eprogn(cddr e)env(extend fenv

    (map car (cadr e))(map (lambda (def)

    (f.make-function (cadr def) (cddr def) env fenv) )(cadr e) ) ) ) ) ...

    flet : , - lambda env, fenv. :

    (flet ((square (x) (* x x))(lambda (x) (square (square x))) )

    , . square.

    2.3. - -

    , -. , - :

    (2 (foo bar hux wok)) hux(-2 (foo bar hux wok)) (hux wok) cadr, ,

    cdr, . car cdr 0 -1. (-1 (-2 )) (-3 ) (2 (-3 )) (5 ).

    :

    ((list + - *) 5 3) (8 2 15)

  • 2. LISP, 1, 2, . . . , 61

    - - . ,

    (map (lambda (f) (f 5 3))(list + - *) )

    , -, : (1 + 2) 3. , DWIM [Tei74, Tei76].

    , -, , - , , , . -, - . -, , . , - .

    (apply (list 2 (list 0 (+ 1 2)))(foo bar hux wok) )

    (hux (foo wok))

    . [. . 2.3]

    2.4. Lisp1 Lisp2 Lisp1 Lisp2,

    ?Scheme Lisp1, -

    , . Lisp2 , . Common Lisp Lisp2, : -, tagbody . . Lispn , - . (, , ) ( , , . .). . , ( - ), .

    Lisp2 . , , [Sen89],

  • 2. LISP, 1, 2, . . . , 62

    Scheme. - Lisp2-, . , funcall, -, . Lisp2 , - .

    , Lisp2-, CommonLisp. f.lookup, - , , wrong. f.lookup. , , - . - , , .

    (define (f.evaluate e env fenv)(if (atom? e)

    (cond ((symbol? e) (lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) )e )

    (else (wrong "Cannot evaluate" e)) )(case (car e)

    ((quote) (cadr e))((if) (if (f.evaluate (cadr e) env fenv)

    (f.evaluate (caddr e) env fenv)(f.evaluate (cadddr e) env fenv) ))

    ((begin) (f.eprogn (cdr e) env fenv))((set!) (update! (cadr e)

    env(f.evaluate (caddr e) env fenv) ))

    ((lambda) (f.make-function (cadr e) (cddr e) env fenv))((function)(cond ((symbol? (cadr e))

    (f.lookup (cadr e) fenv) )((and (pair? (cadr e)) (eq? (car (cadr e)) lambda))(f.make-function(cadr (cadr e)) (cddr (cadr e)) env fenv ) )

    (else (wrong "Incorrect function" (cadr e))) ) )((flet)(f.progn (cddr e)

    env(extend fenv (map car (cadr e))

    (map (lambda (def)

  • 2. LISP, 1, 2, . . . , 63

    (f.make-function (cadr def)(cddr def)env fenv ) )

    (cadr e) ) ) ) )((labels)(let ((new-fenv (extend fenv

    (map car (cadr e))(map (lambda (def) void)

    (cadr e) ) )))(for-each (lambda (def)

    (update! (car def)new-fenv(f.make-function (cadr def) (cddr def)

    env new-fenv ) ) )(cadr e) )

    (f.eprogn (cddr e) env new-fenv) ) )(else (f.evaluate-application (car e)

    (f.evlis (cdr e) env fenv)envfenv )) ) ) )

    (define (f.evaluate-application fn args env fenv)(cond ((symbol? fn)

    ((f.lookup fn fenv) args) )((and (pair? fn) (eq? (car fn) lambda))(f.eprogn (cddr fn)

    (extend env (cadr fn) args)fenv ) )

    (else (wrong "Incorrect functional term" fn)) ) )

    (define (f.lookup id fenv)(if (pair? fenv)

    (if (eq? (caar fenv) id)(cdar fenv)(f.lookup id (cdr fenv)) )

    (lambda (values)(wrong "No such functional binding" id) ) ) )

    , [GP88], Lisp1 Lisp2 . , , - :

    (defun foo (list)(list list) )

    Lisp1, (list list) ,2

    2 , , ., (number? number?).

  • 2. LISP, 1, 2, . . . , 64

    Lisp2 . CommonLisp . , - ; .

    Lisp1 Lisp2 -. Common Lisp , lambda-, , , - . , Common Lisp , lambda. , - (... (lambda ...) ...) Common Lisp. - lambda function. function , ((function(lambda ...)) ...) . , : , . , , (function (lambda ...)), funcall , .

    , , . - . list , list . Scheme , . .

    2.5. .

    : env fenv. , , - . , , . , - ( ILOG Talk, EuLisp, ISLisp) - . . , .

    . (bindings) . - ( , ,

  • 2. LISP, 1, 2, . . . , 65

    , . .), ( , , , ). - . , , . , .

    . -, - ; ; , . , , -, . , . , - . - Scheme:

    x x (set! x ...) (lambda (... x ...) ...) (define x ...)

    , . , , . , - . , . , - . , - : lambda-, , let let*, lambda-. , , . , - , , .

    , Lisp2, , :

    (f ...) (function f ) (flet (... (f ...) ...) ...) (defun)

  • 2. LISP, 1, 2, . . . , 66

    2.5.1.

    , - . , - :

    (dynamic d) (dynamic-set! d ...) (dynamic-let (... (d ...) ...) ...)

    : 3 dynamic-let, let flet; dynamic, dynamic-set!.

    , . - f.evaluate : denv. . , - Lisp3, df., - . . ( flet .)

    (define (df.evaluate e env fenv denv)(if (atom? e)

    (cond ((symbol? e) (lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) )e )

    (else (wrong "Cannot evaluate" e)) )(case (car e)

    ((quote) (cadr e))((if) (if (df.evaluate (cadr e) env fenv denv)

    (df.evaluate (caddr e) env fenv denv)(df.evaluate (cadddr e) env fenv denv) ))

    ((begin) (df.eprogn (cdr e) env fenv denv))((set!) (update! (cadr e)

    env(df.evaluate (caddr e) env fenv denv) ))

    ((function)(cond ((symbol? (cadr e))

    (f.lookup (cadr e) fenv) )((and (pair? (cadr e)) (eq? (car (cadr e)) lambda))

    3 , () .

  • 2. LISP, 1, 2, . . . , 67

    (df.make-function(cadr (cadr e)) (cddr (cadr e)) env fenv ) )

    (else (wrong "Incorrect function" (cadr e))) ) )((dynamic) (lookup (cadr e) denv))((dynamic-set!)(update! (cadr e)

    denv(df.evaluate (caddr e) env fenv denv) ) )

    ((dynamic-let)(df.eprogn (cddr e)

    envfenv(extend denv

    (map car (cadr e))(map (lambda (e)

    (df.evaluate e env fenv denv) )(map cadr (cadr e)) ) ) ) )

    (else (df.evaluate-application (car e)(df.evlis (cdr e) env fenv denv)envfenvdenv )) ) ) )

    (define (df.evaluate-application fn args env fenv denv)(cond ((symbol? fn) ((f.lookup fn fenv) args denv))

    ((and (pair? fn) (eq? (car fn) lambda))(df.eprogn (cddr fn)

    (extend env (cadr fn) args)fenvdenv ) )

    (else (wrong "Incorrect functional term" fn)) ) )

    (define (df.make-function variables body env fenv)(lambda (values denv)

    (df.eprogn body (extend env variables values) fenv denv) ) )

    (define (df.eprogn e* env fenv denv)(if (pair? e*)

    (if (pair? (cdr e*))(begin (df.evaluate (car e*) env fenv denv)

    (df.eprogn (cdr e*) env fenv denv) )(df.evaluate (car e*) env fenv denv) )

    empty-begin ) )

    , denv, - df.evaluate df.eprogn, -. , df.evaluate

  • 2. LISP, 1, 2, . . . , 68

    denv, . -: df.evaluate-application - . [. . 38], .

    -. , - . , - . , . -, , , . : , , ISLisp; - , EuLisp; , Common Lisp. [. . 70]

    : , - , . - - dynamic. . , Lisp3 - , .

    . - , , , , - (, , - ). , . - -. , let dynamic-let, dynamic-let :

    1) ;

    2) , -;

    3) .

    dynamic-let - .

  • 2. LISP, 1, 2, . . . , 69

    . Common Lisp - *print-base*, *print-circle* . . - , , - , . , - , , - (print ) (print escape-? ? pretty-print? ? -? -gensym?). . , .

    Scheme -. (display ) 4 (display ). , , . . with-output-to-file , . current-output-port. ,5 :

    (define (display-cyclic-spine list)(define (scan l1 l2 flip)

    (cond ((atom? l1) (unless (null? l1)(display " . ") (display l1) )

    (display ")") )((eq? l1 l2) (display "...)"))(else (display (car l1))

    (when (pair? (cdr l1)) (display " "))(scan (cdr l1)

    (if (and flip (pair? l2))(cdr l2)l2 )

    (not flip) ) ) ) )(display "(")(scan list (cons 42 list) #f) )

    (display-cyclic-spine ; (1 2 3 4 1 ...)(let ((l (list 1 2 3 4)))

    (set-cdr! (cdddr l) l)l ) )

    4 display, -. Scheme . , .

    5. list-length Common Lisp.

  • 2. LISP, 1, 2, . . . , 70

    Scheme:

    , (current-output-port) (with-output-to-file - )

    Common Lisp -. print write , *standard-output*.6 7with-output-to-file :

    (define (with-output-to-file filename thunk)(dynamic-let ((*standard-output* (open-input-file filename)))

    (thunk) ) )

    2.5.2. Common Lisp

    Common Lisp , . dynamic-let, :

    (dynamic-let ((x )) (let ((x )) ) (declare (special x))

    )

    , - x dynamic, x. , (declare(special x)) : , let x , x let (dynamic x).

    , - x, . , , x (locally(declare (special x)) x). dynamic.

    Common Lisp . , :

    6 , , - .

    7, Common Lisp. Lisp3, .

  • 2. LISP, 1, 2, . . . , 71

    (define (df.evaluate e env fenv denv)(if (atom? e)

    (cond ((symbol? e) (cl.lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) )e )

    (else (wrong "Cannot evaluate" e)) )(case (car e)

    ((quote) (cadr e))((if) (if (df.evaluate (cadr e) env fenv denv)

    (df.evaluate (caddr e) env fenv denv)(df.evaluate (cadddr e) env fenv denv) ))

    ((begin) (df.eprogn (cdr e) env fenv denv))((set!) (update! (cadr e)

    env(df.evaluate (caddr e) env fenv denv) ))

    ((function)(cond ((symbol? (cadr e))

    (f.lookup (cadr e) fenv) )((and (pair? (cadr e)) (eq? (car (cadr e)) lambda))(df.make-function(cadr (cadr e)) (cddr (cadr e)) env fenv ) )

    (else (wrong "Incorrect function" (cadr e))) ) )((dynamic) (lookup (cadr e) denv))((dynamic-set!)(update! (cadr e)

    denv(df.evaluate (caddr e) env fenv denv) ) )

    ((dynamic-let)(df.eprogn (cddr e)

    (special-extend env(map car (cadr e)) )

    fenv(extend denv

    (map car (cadr e))(map (lambda (e)

    (df.evaluate e env fenv denv) )(map cadr (cadr e)) ) ) ) )

    (else (df.evaluate-application (car e)(df.evlis (cdr e) env fenv denv)envfenvdenv )) ) ) )

    (define (special-extend env variables)(append variables env) )

  • 2. LISP, 1, 2, . . . , 72

    (define (cl.lookup var env denv)(let look ((env env))

    (if (pair? env)(if (pair? (car env))

    (if (eq? (caar env) var)(cdar env)(look (cdr env)) )

    (if (eq? (car env) var); ; (let lookup-in-denv ((denv denv))

    (if (pair? denv)(if (eq? (caar denv) var)

    (cdar denv)(lookup-in-denv (cdr denv)) )

    ; ; , (lookup var env.global) ) )

    (look (cdr env)) ) )(wrong "No such binding" var) ) ) )

    , . dynamic-let - , , , . - (cl.lookup): , ( ), . , - , , Common Lisp .

    Lisp3, Common Lisp:

    (dynamic-let ((x 2))(+ x ; x

    (let ((x (+ ; x x ))) ;

    (+ x ; (dynamic x) ) ) ) ) ;

    8

    2.5.3.

    . Scheme - , -

  • 2. LISP, 1, 2, . . . , 73

    . , , . ; . -. - , . Scheme.

    : env denv. , : , - CommonLisp. . , - , , , ! , dd.

    (define (dd.evaluate e env denv)(if (atom? e)

    (cond ((symbol? e) (lookup e env))((or (number? e)(string? e)(char? e)

    (boolean? e)(vector? e) )e )

    (else (wrong "Cannot evaluate" e)) )(case (car e)

    ((quote) (cadr e))((if) (if (dd.evaluate (cadr e) env denv)

    (dd.evaluate (caddr e) env denv)(dd.evaluate (cadddr e) env denv) ))

    ((begin) (dd.eprogn (cdr e) env denv))((set!) (update! (cadr e) env

    (dd.evaluate (caddr e) env denv) ))((lambda) (dd.make-function (cadr e) (cddr e) env))(else (invoke (dd.evaluate (car e) env denv)

    (dd.evlis (cdr e) env denv)denv )) ) ) )

    (define (dd.make-function variables body env)(lambda (values denv)

    (dd.eprogn body (extend env variables values) denv) ) )

    (define (dd.evlis e* env denv)(if (pair? e*)

    (if (pair? (cdr e*))(cons (dd.evaluate (car e*) env denv)

    (dd.evlis (cdr e*) env denv) )

  • 2. LISP, 1, 2, . . . , 74

    (list (dd.evaluate (car e*) env denv)) )() ) )

    (define (dd.eprogn e* env denv)(if (pair? e*)

    (if (pair? (cdr e*))(begin (dd.evaluate (car e*) env denv)

    (dd.eprogn (cdr e*) env denv) )(dd.evaluate (car e*) env denv) )

    empty-begin ) )

    , . bind-with-dynamic-extent; , bind/de. tag; value, - ; thunk, , .

    (definitial bind/de(lambda (values denv)

    (if (= 3 (length values))(let ((tag (car values))

    (value (cadr values))(thunk (caddr values)) )

    (invoke thunk ()(extend denv (list tag) (list value)) ) )

    (wrong "Incorrect arity" bind/de) ) ) )

    . - , - , assoc/de , . , .

    (definitial assoc/de(lambda (values current.denv)

    (if (= 2 (length values))(let ((tag (car values))

    (default (cadr values)) )(let look ((denv current.denv))

    (if (pair? denv)(if (eqv? tag (caar denv))

    (cdar denv)(look (cdr denv)) )

    (invoke default (list tag) current.denv) ) ) )(wrong "Incorrect arity" assoc/de) ) ) )

    (eqv? equal?). [. . 2.4]

  • 2. LISP, 1, 2, . . . , 75

    :

    (bind/de x 2(lambda () (+ (assoc/de x error)

    (let ((x (+ (assoc/de x error)(assoc/de x error) )))

    (+ x (assoc/de x error)) ) )) ) 8 ,

    . - . , - , - ( ). , , .8 , . . - Common Lisp.

    , bind/de assoc/de -. ,, . : . , - , : ( ) , .

    2.5.4.

    , - : - . Lisp3 , Common Lisp.

    , , - , . Lisp, ? Scheme, : env denv. , , - Scheme Lisp1. , ( evaluate dd.evaluate), bind/de assoc/de. - , -, ; ,

    8 nil if ( , ).

  • 2. LISP, 1, 2, . . . , 76

    . call/cc.

    , , Lisp1, - , Lisp2 . - , - Lisp, . [. . 2.6] , - ( , ), - Lisp2.

    , - . Common Lisp , - . , , . , ; , Common Lisp . , Lisp 1.5 - , csetq (setq ).

    x x (csetq x ) (csetq x )

    . - foo , . - Lisp 1.5 : foo, ; - . : (!) csetq, . , Lisp 1.5 Scheme, : Scheme , , .

    . - , .

  • 2. LISP, 1, 2, . . . , 77

    2.6. , ,

    . .

    2.6.1.

    , , :

    (define (fact n)(if (= n 0) 1

    (* n (fact (- n 1))) ) )

    , , , define, , , :

    (set! fact (lambda (n)(if (= n 1) 1

    (* n (fact (- n 1))) ) ))

    , fact. , fact . , -. ( , , ) -, , , . , , . , . , - , . , - , .[. . 142]

    , , , . ; , , . define, . -, . , :

    (define (display-pi)(display pi) )

    (define pi 2.7182818285) ; ,

  • 2. LISP, 1, 2, . . . , 78

    (define (print-pi)(display pi) )

    (define pi 3.1415926536)

    display-pi? pi, . define ; define , ?

    . -: ( ML) ( ).

    , , ( , ), . display-pi , pi, . display-pi : pi( ). print-pi , , ( 2.7182818285), . pi pi, - . :

    (let ((display-pi (lambda () (display pi))))(let ((pi 2.7182818285))

    (let ((print-pi (lambda () (display pi))))(let ((pi 3.1415926536))

    ... ) ) ) )

    , , . , - , , . - - . ( - forward ISO C [ISO90].)

    . ; , lambda-, : fact? -, fact, . : fact, - , ( , ). fact , - . , -

  • 2. LISP, 1, 2, . . . , 79

    . , - , . , define fact , , - fact. : - .

    2.6.2.

    , . odd? even?, ( -) . - :

    (define (even? n)(if (= n 0) #t (odd? (- n 1))) )

    (define (odd? n)(if (= n 0) #f (even? (- n 1))) )

    , ; even? odd?. , , - : , , , , - odd? even?. , , .

    - , . , - , , . ( , .) ,- Lisp 1.5 define :

    (define ((even? (lambda (n) (if (= n 0) #t (odd? (- n 1)))))(odd? (lambda (n) (if (= n 0) #f (even? (- n 1))))) ))

    , - .

    , ?

    2.6.3. Lisp2 , -

    fact , - fact . -, fact fact . fact

  • 2. LISP, 1, 2, . . . , 80

    - . : , , - . Lisp2:

    (flet ((fact (n) (if (= n 0) 1(* n (fact (- n 1))) )))

    (fact 6) )

    flet fact . , flet. , fact fact fact, - flet, - fact flet. ( ), .

    Lisp 1.5. label, . :

    (label fact (lambda (n) (if (= n 0) 1(* n (fact (- n 1))) )))

    , . , , fact .

    , , Lisp 1.5 Lisp2, label, , . - , [HS75], - : labels. , flet, , , . fact, odd? even?:

    (labels ((fact (n) (if (= n 0) 1(* n (fact (- n 1))) ) ))

    (fact 6) ) 720

    (funcall (labels ((even? (n) (if (= n 0) #t (odd? (- n 1))))(odd? (n) (if (= n 0) #f (even? (- n 1)))) )

    (function even?) )4 ) #t

    Lisp2 - : flet labels.

    2.6.4. Lisp1

    Lisp1; . letrec ( let) labels.

  • 2. LISP, 1, 2, . . . , 81

    Scheme let :

    (let ((1 1)(2 2)...

    (n n) )... )

    :

    ((lambda (1 2 ... n) ...)1 2 ... n )

    , . -: 1, 2, . . . , n; -1, 2, . . . , n ; , , let, - begin, let.

    , let -, lambda; , let . ( Scheme: let - .) , let , . , - let ; .

    , Lisp2, - . letrec, labels.

    letrec , let. :

    (letrec ((even? (lambda (n) (if (= n 0) #t (odd? (- n 1)))))(odd? (lambda (n) (if (= n 0) #f (even? (- n 1))))) )

    (even? 4) )

    letrec let , - - , letrec. , - letrec, , let, . - letrec. - . , letrec. - , . , :

    (let ((even? void) (odd? void))(set! even? (lambda (n) (if (= n 0) #t (odd? (- n 1)))))(set! odd? (lambda (n) (if (= n 0) #t (even? (- n 1)))))(even? 4) )

  • 2. LISP, 1, 2, . . . , 82

    even? odd?. ( , let lambda - .) - , , - even? odd?. , , , . even? odd? - , , , .

    , - -: , let , ,letrec, , , , - . , - . [. . 2.9]

    letrec

    letrec : - . letrec - , ; labels CommonLisp . Scheme - :

    (letrec ((x (/ (+ x 1) 2))) x)

    , x . ,,

    = + 1

    2

    x . 1.

    , ?(letrec ((x (+ x 1))) x) ; = + 1(letrec ((x (+ (power x 37) 1))) x) ; = 37 + 1

    , , S--, , - [MS80]. , - :

    (letrec ((foo (cons bar foo))) foo)

    - (bar bar bar ...), [FW76, PJ87], ( ):

  • 2. LISP, 1, 2, . . . , 83

    (let ((foo (cons bar wait)))(set-cdr! foo foo)foo )

    , . , - , , letrec, -. x x. , , -. , Scheme , , , -, , . :

    (letrec ((x (+ y 1))(y 2) )

    x )

    y x, . - , y, - , . Scheme ML - - ., ; , - 9 :

    (letrec ((x y) (y x)) (list x y))

    - define. : , .

    2.6.5.

    Scheme letrec ; , . , - letrec- Scheme. , letrec void. , , - . , - Scheme .

    , # [. . 33] void. : -

    9 (42 42) , 42?

  • 2. LISP, 1, 2, . . . , 84

    , car; , , cons, , - #:

    (letrec ((foo (cons foo foo))) (cdr foo))

    , - , . , , .

    , . # -, . . , void - #, . , : - # , , , . - , :

    (define (fact n)(if (eq? n #)

    (wrong "Uninitialized n")(if (= n 0) 1

    (* n (fact (- n 1))) ) ) )

    letrec. # , , - . , , .

    , - . , let Common Lisp, , Scheme:

    (let ( ...)... )

    , , . , , . - letrec. tempi -: , letrec .

  • 2. LISP, 1, 2, . . . , 85

    (letrec ((1 1) (let (1 ... n)... (let ((temp1 1)(n n) ) ...

    ) (tempn n) )(set! 1 temp1)...(set! n tempn) ) )

    , : - , - . let - , , - . evaluate:

    ...((let)(eprogn (cddr e)

    (extend env(map (lambda (binding)

    (if (symbol? binding) binding(car binding) ) )

    (cadr e) )(map (lambda (binding)

    (if (symbol? binding) the-uninitialized-marker(evaluate (cadr binding) env) ) )

    (cadr e) ) ) ) ) ...

    the-uninitialized-marker . , , :

    (define the-uninitialized-marker (cons not initialized))

    , - lookup. update! . wrong : .

    (define (lookup id env)(if (pair? env)

    (if (eq? (caar env) id)(let ((value (cdar env)))

    (if (eq? value the-uninitialized-marker)(wrong "Uninitialized binding" id)value ) )

    (lookup id (cdr env)) )(wrong "No such binding" id) ) )

  • 2. LISP, 1, 2, . . . , 86

    , - letrec, - .

    2.6.6.

    letrec, , . , - , ; , , - , ?

    : , - , . . -, , - , - , .

    , , letrec , ML . evaluate :

    ...((letrec)(let ((new-env (extend env

    (map car (cadr e))(map (lambda (binding) the-uninitialized-marker)

    (cadr e) ) )))(map (lambda (binding) ; map !

    (update! (car binding)new-env(evaluate (cadr binding) new-env) ) )

    (cadr e) )(eprogn (cddr e) new-env) ) ) ...

    , , update!; - . , , map, , for-each, - .10

    10, , .

  • 2. LISP, 1, 2, . . . , 87

    letrec

    - , . - , . letrec , .

    (letrec ((fact (lambda (n)(if (= n 0) 1 (* n (fact (- n 1)))) )))

    (letrec ((odd? (lambda (n) (if (= n 0) #f (even? (- n 1)))))(even? (lambda (n) (if (= n 0) #t (odd? (- n 1))))) )

    ... ) )

    letrec fact, odd? even?, .

    -, , Y-. -, , () = . Y - . -:

    : Y : : Y = (Y )

    , Y

    (let ((W (lambda (w)(lambda (f)

    (f ((w w) f)) ) )))(W W) )

    . , Y ( ), , ( ) (( ) )? , , .. (( ) ). .

    , - Scheme . ((w w) f) , ( -)-, . - Z-, (lambda (x) (... x)) -:

  • 2. LISP, 1, 2, . . . , 88

    (define fix(let ((d (lambda (w)

    (lambda (f)(f (lambda (x) (((w w) f) x))) ) )))

    (d d) ) )

    , . . meta-fact:

    (define (meta-fact f)(lambda (n)

    (if (= n 0) 1(* n (f (- n 1))) ) ) )

    . , -, (meta-fact fact) , fact, . , - meta-fact: = (meta-fact ). - :

    f = (lambda (n)(if (= n 0) 1

    (* n (f (- n 1))) ) )

    , ? , !- , , -

    . (, , .), :

    (define (another-fact n)(cond ((< n 1) (- n))

    ((= n 1) 1)(else (* n (another-fact (- n 1)))) ) )

    , , another-fact meta-fact. , - , , : . , fact . another-fact -, - , ,11 . , - .

    11 . [Man74].

  • 2. LISP, 1, 2, . . . , 89

    fact , , - . :

    (define (fact n)(if (= n 0) 1

    (* n (fact (- n 1))) ) )

    fact. define - fact. [. . 77] define - . , define , . - - .

    fix, Z-, , ((fix meta-fact) 3). , , , - , .

    ((fix meta-fact) 3) (((d d)

    d (lambda (w)(lambda (f)(f (lambda (x)

    (((w w) f) x) )) ) )meta-fact )

    3 )

    (((lambda (f) ; I(f (lambda (x)

    (((w w) f) x) )) )w (lambda (w)

    (lambda (f)(f (lambda (x)

    (((w w) f) x) )) ) )meta-fact )

    3 )

    ((meta-fact (lambda (x)(((w w) f) x) ))

    w (lambda (w)(lambda (f)

    (f (lambda (x)(((w w) f) x) )) ) )

    3 )

  • 2. LISP, 1, 2, . . . , 90

    ((lambda (n)(if (= n 0) 1

    (* n (f (- n 1))) ) )f (lambda (x)

    (((w w) meta-fact) x) )w

    ...

    (lambda (w)(lambda (f)

    (f (lambda (x)(((w w) f) x) )) ) )

    3 ) (* 3 (f 2))

    f (lambda (x)(((w w) meta-fact) x) )

    w ...

    (lambda (w)(lambda (f)

    (f (lambda (x)(((w w) f) x) )) ) )

    (* 3 (((w w) meta-fact) 2))w (lambda (w)

    (lambda (f)(f (lambda (x)

    (((w w) f) x) )) ) ) (* 3 (((lambda (f) ; II

    (f (lambda (x)(((w w) f) x) )) )

    w (lambda (w)(lambda (f)

    (f (lambda (x)(((w w) f) x) )) ) )

    meta-fact )2 ) )

    , , II , I. , - :

    (* 3 (* 2 (((lambda (f)(f (lambda (x)

    (((w w) f) x) )) )w (lambda (w)

    (lambda (f)(f (lambda (x)

    (((w w) f) x) )) ) )meta-fact )

    1 )))

  • 2. LISP, 1, 2, . . . , 91

    (* 3 (* 2 ((meta-fact (lambda (x)(((w w) meta-fact) x) ))

    w ...

    (lambda (w)(lambda (f)

    (f (lambda (x)(((w w) f) x) )) ) )

    1 ))) (* 3 (* 2 ((lambda (n)

    (if (= n 0) 1(* n (f (- n 1))) ) )

    f ...1 )))

    (* 3 (* 2 (if (= n 0) 1 (* n (f (- n 1))))))n 1f ...

    (* 3 (* 2 1))

    6 , -

    , . :

    (lambda (x)(((w w) f) x) )

    f meta-factw (lambda (w)

    (lambda (f)(f (lambda (x)

    (((w w) f) x) )) ) ) , , -

    , , - .

    - , fix, . Y ( fix), define ; -. , define , fact :

    (fix (lambda (fact)(lambda (n)

    (if (= n 0) 1(* n (fact (- n 1))) ) ) ))

    , , - , :

  • 2. LISP, 1, 2, . . . , 92

    (define odd-and-even(fix (lambda (f)

    (lambda (which)(case which

    ((odd) (lambda (n) (if (= n 0) #f((f even) (- n 1)) )))

    ((even) (lambda (n) (if (= n 0) #t((f odd) (- n 1)) ))) ) ) )) )

    (define odd? (odd-and-even odd))(define even? (odd-and-even even))

    : , letrec. ( , . [Roz92, Ser93].) , , . - , [PJ87], , , -, , -, fix - . , fix ,12 - , -. fix (

    ( ) ( )) ( ) fix : (d d). ,

    : = ( )

    , , - fix , .

    2.7. , -

    . , -, . lambda - . , (!) . . , - , .

    12 [MAE+62]: , - .

  • 2. LISP, 1, 2, . . . , 93

    -. Lisp1 () ( ), -. , -, . - , , , , , -, , .

    . - . , - , - .

    . , . , - lambda, . .

    , .

    2.8. 2.1 Common Lisp. Scheme?

    (funcall (function funcall) (function funcall) (function cons) 1 2)

    2.2 -Common Lisp ? ?

    (defun test (p)(function bar) )

    (let ((f (test #f)))(defun bar (x) (cdr x))(funcall f (1 . 2)) )

    2.3 - 2.3 [. . 60]. .

  • 2. LISP, 1, 2, . . . , 94

    2.4 assoc/de - ( eq?, equal? . .) , . .

    2.5 bind/de assoc/de, , - dynamic-let, dynamic dynamic-set!.

    2.6 getprop putprop, - . ; putprop, getprop. , ,

    (begin (putprop symbol key value)(getprop symbol key) ) value

    2.7 label Lisp1.

    2.8 labels Lisp2.

    2.9 , letrec let set! , - -.

    2.10 Scheme - : . - fix2, . fixN, .

    2.11 NfixN, - . , , :

    (let ((odd-and-even(NfixN (list (lambda (odd? even?) ; odd?

    (lambda (n)(if (= n 0) #f (even? (- n 1))) ) )

    (lambda (odd? even?) ; even?(lambda (n)

    (if (= n 0) #t (odd? (- n 1))) ) ) )) ))(set! odd? (car odd-and-even))(set! even? (cadr odd-and-even)) )

    2.12 klop. - ? , (klop) fix.

  • 2. LISP, 1, 2, . . . , 95

    (define klop(let ((r (lambda (s c h e m)

    (lambda (f)(f (lambda (n)

    (((m e c h e s) f) n) )) ) )))(r r r r r r) ) )

    2.13 hyper-fact :

    (define (hyper-fact f)(lambda (n)

    (if (= n 0) 1(* n ((f f) (- n 1))) ) ) )

    ((hyper-fact hyper-fact) 5)?

    - [SS78a]

    [Mos70] Lisp1 Lisp2 [GP88].

    [Gor88] -. Y [Gab88].

  • 3

    :

    , . - . , . - Scheme, . - . [Moz87], - . , ; , , . - .

    , , -, . , , (escapes): - , , , . - , , , - .

    Lisp 1.5 prog. , - , , goto. , , .1 , prog , . , :

    1, [WH89].

  • 3. : 97

    (defun fact (n) Common Lisp(prog (r)

    (setq r 1)loop (cond ((= n 1) (return r)))

    (setq r (* n r))(setq n (- n 1))(go loop) ) )

    prog ( r). (- ) ( ). - , progn. prog nil. prog . go ( - ), prog return. Lisp 1.5 : go return cond .

    return prog, -. Lisp 1.5 , , - . . , - . , return :

    (defun fact2 (n) Common Lisp(prog (r)

    (setq r 1)loop (setq r (* (cond ((= n 1) (return r))

    (else n) )r ))

    (setq n (- n 1))(go loop) ) )

    prog return -, , - : , . prog , , return . , , , .

    , - . , . :

  • 3. : 98

    (define (find-symbol id tree)(if (pair? tree)

    (or (find-symbol id (car tree))(find-symbol id (cdr tree)) )

    (eq? tree id) ) )

    , foo : (((a . b) . (foo . c)) .(d . e)). , , , or, #t, . :

    (find-symbol foo (((a . b) . (foo . c)) . (d . e))) (or (find-symbol foo ((a . b) . (foo . c)))

    (find-symbol foo (d . e)) ) (or (or (find-symbol foo (a . b))

    (find-symbol foo (foo . c)) )(find-symbol foo (d . e)) )

    (or (or (or (find-symbol foo a)(find-symbol foo b) )

    (find-symbol foo (foo . c)) )(find-symbol foo (d . e)) )

    (or (or (find-symbol foo b)(find-symbol foo (foo . c)) )

    (find-symbol foo (d . e)) ) (or (find-symbol foo (foo . c))

    (find-symbol foo (d . e)) ) (or (or (find-symbol foo foo)

    (find-symbol foo c) )(find-symbol foo (d . e)) )

    (or (or #t(find-symbol foo c) )

    (find-symbol foo (d . e)) ) (or #t

    (find-symbol foo (d . e)) ) #t -

    . , or , .

    -. : - . - , - , - . better-map, - . [. . 106]

  • 3. : 99

    , , , , , , , , - . (continuation). , .

    . , (+ 3(* 2 4)) (* 2 4) , 3, . . , , , - . (* 2 4) (lambda (x) (+ 3 x)), , .

    , -. (+ 3 []), [] , .

    , . - , , . (if (foo) 1 2) (foo) (lambda (x) (if x 12)) (if [] 1 2).

    , . , , .

    3.1. , -

    . prog , let. , , ( ) catch throw.

    3.1.1. catch/throw

    catch :

    (catch ...)

    catch. , ,

  • 3. : 100

    , . , , . , - , , , . .

    catch -, progn begin. , catch . throw.

    throw :

    (throw )

    , catch - . , - , catch throw.

    - catch throw. id, ; .

    (define (find-symbol id tree)(define (find tree)

    (if (pair? tree)(or (find (car tree))

    (find (cdr tree)) )(if (eq? tree id)

    (throw find #t)#f ) ) )

    (catch find(find tree) ) )

    catch, , , throw. -, . catch - , . throw , . ,throw catch . catch - find-symbol, throw - , find-symbol.

  • 3. : 101

    :

    (throw ...) , (catch ...)

    , catch , , - (), - , begin. . catch throw, .

    throw , . , Common Lisp, , catch, , , . throw - , : , catch, -.

    - . , , - . , , catch-? ? , (throw (throw ))? .

    3.1.2. block/return-from

    , catch throw, . throw , - catch- . , , , - , Common Lisp. block return-from catch throw.

    block :

    (block ...)

    . block . block progn - block. return-from.

  • 3. : 102

    return-from :

    (return-from )

    ; : return-from block - , - lambda-. return-from block .

    , - :

    (return-from ...) , (block ...)

    2 :

    (define (find-symbol id tree)(block find

    (letrec ((find (lambda (tree)(if (pair? tree)

    (or (find (car tree))(find (cdr tree)) )

    (if (eq? id tree)(return-from find #t)#f ) ) )))

    (find tree) ) ) )

    , catch find

    block find;

    block, return-from find.

    block . - , , block, . return-from - #t , ( , ), , find. - , , - catch. , catch3 block:

    2 letrec, Scheme define block, (let () (define ...)) - ().

    3 catch block label. , - ( ) .

  • 3. : 103

    (define *active-catchers* ())

    (define-syntax throw(syntax-rules ()

    ((throw tag value)(let* ((label tag) ;

    (escape (assv label *active-catchers*)) ) ; (if (pair? escape)

    ((cdr escape) value)(wrong "No associated catch to" label) ) ) ) ) )

    (define-syntax catch(syntax-rules ()

    ((catch tag . body)(let* ((saved-catchers *active-catchers*)

    (result (block label(set! *active-catchers*

    (cons (cons tag(lambda (x)

    (return-from label x) ) )*active-catchers* ) )

    . body )) )(set! *active-catchers* saved-catchers)result ) ) ) )

    catch/throw - assv4 throw. , . ( *active-catchers*) catch- ( ). catch ( , - throw). *active-catchers* - . -, catch throw - .

    3.1.3.

    , , catch - block, *active-catchers* . [Fel90, Bak92c], , - ( *active-catchers*).

    4, eqv?.

  • 3. : 104

    , catch block, : unwind-protect.5

    , . catch block , , catch, catch. - . - , , . - *active-catchers* , catch block , .

    (define-syntax throw(syntax-rules ()

    ((throw tag value)(let* ((label tag)

    (escape (assv label (dynamic *active-catchers*))) )(if (pair? escape)

    ((cdr escape) value)(wrong "No associated catch to" label) ) ) ) ) )

    (define-syntax catch(syntax-rules ()

    ((catch tag . body)(block label

    (dynamic-let ((*active-catchers*(cons (cons tag (lambda (x)

    (return-from label x) ))(dynamic *active-catchers) ) ))

    . body ) ) ) ) )

    , block Common Lisp, , block. catch. , , block, , catch: throw return-from , . - :

    ((block foo(lambda (x) (return-from foo x)) )

    33 )

    5 : block return-from , catch throw. - , .

  • 3. : 105

    - foo 33, foo, - . , , foo. block . , - foo, . , - , . , , block. :

    (block foo(let ((f1 (lambda (x) (return-from foo x))))

    (* 2 (block foo(f1 1) )) ) ) 1

    , , block foo

    catch foo:

    (catch foo(let ((f1 (lambda (x) (throw foo x))))

    (* 2 (catch foo(f1 1) )) ) ) 2

    f1 catch, foo, , ; -, catch - 2.

    3.1.4. catch block

    , catch block : . , return-from , throw . block , return-from , - block, . , , , . - : .

    . - : - , . :

  • 3. : 106

    (define (foo)(catch foo (* 2 (bar))) )

    (define (bar)(+ 1 (throw foo 5)) )

    (foo) 5block ,

    catch throw . (throw foo ...) - (* 2 (bar)) .

    catch foo

    block foo , return-from (block foo ...) , bar. . .

    (catch not-a-pair(better-map (lambda (x)

    (or (pair? x)(throw not-a-pair x) ) )

    (hack-and-return-list) ) )

    , , better-map - map; , , , (hack-and-return-list) - , ; , , better-map, :

    (define (better-map f L)(define (loop L1 L2 flag)

    (if (pair? L1)(if (eq? L1 L2)

    (throw not-a-pair L)(cons (F (car L1))

    (loop (cdr L1)(if flag (cdr L2) L2)(not flag) ) ) ) ) )

    (loop L (cons ignore L) #t) )

    better-map , map - ( ). (hack-and-return-list) : #1=((foo . hack). #1#),6 better-map not-a-pair . : , - better-map, . ,

    6 Common Lisp . Scheme (let ((p (list (cons foo hack)))) (set-cdr! p p) p).

  • 3. : 107

    better-map , , , - -. , catch , , , :

    (let ((tag (list not-a-pair)))(catch tag

    (better-map (lambda (x)(or (pair? x)

    (throw tag x) ) )(hack-and-return-list) ) ) )

    , , block catch(, ). .

    (define-syntax block(syntax-rules ()

    ((block label . body)(let ((label (list label)))

    (catch label . body) ) ) ) )(define-syntax return-from

    (syntax-rules ()((return-from label value)(throw label value) ) ) )

    block - . , return-from, block., label, -. , - gensym, , catch throw .

    3.1.5.

    Scheme, 1975 , -, catch block, . . , - , . [Lan65] , - call/cc Scheme.

    , . -, , , :

    (...)

  • 3. : 108

    , . call/cc:

    (call/cc ...)

    , k , - . ? , k call/cc, . - , ,7 k , call/cc:

    (call/cc (lambda (k) ...))

    k , - - call/cc. , k , , - lambda. call/cc k , k. k, , call/cc:

    (call/cc (lambda (k) (+ 1 (k 2)))) 2 .

    , - : continue. :

    (call/cc (lambda (k) (+ 1 (continue k 2)))) 2 , -

    , (lambda (v) (continue k v)). - , .

    . : call-with-current-continuation. , call/cc:

    (define (find-symbol id tree)(call/cc(lambda (exit)

    (define (find tree)(if (pair? tree)

    (or (find (car tree))(find (cdr tree)) )

    (if (eq? tree id) (exit #t) #f) ) )(find tree) ) ) )

    find-symbol - , exit. - , exit,

    7 Scheme , . (call/cc list) .

  • 3. : 109

    find-symbol, -, find-symbol.

    -, call/cc. , block/catch.

    (define (fact n)(let ((r 1) (k void))

    (call/cc (lambda (c) (set! k c) void))(set! r (* r n))(set! n (- n 1))(if (= n 1) r (k recurse)) ) )

    , c k, :

    k = (lambda (u)(set! r (* r n))(set! n (- n 1))(if (= n 1) r (k recurse)) )

    r 1k kn

    k k . -, , - ; k - , n . ,, .

    k call/cc. , , :

    (define (fact n)(let ((r 1) (k (call/cc (lambda (c) c))))

    (set! r (* r n))(set! n (- n 1))(if (= n 1) r (k k)) ) )

    (k k) , - k. :

    (lambda (u)(let ((k u))

    (set! r (* r n))(set! n (- n 1))(if (= n 1) r (k k)) ) )

    r 1n

    . (. [CHO88,

  • 3. : 110

    HDB90, Mat92].) ? , - , . - , : , . , : , .

    , -. (call/cc ...) : - . - ( 8), , , .

    call/cc -. - , , ( ). ( ), . , , .

    , call/cc goto, considered harmful. call/cc , , , , .

    call/cc, -, . , call/cc :

    (call/cc ) ( k) k call/cc, - -. call/cc k , . , k , , , :

    (call/cc (lambda (k) 1515)) 1515- .

    call/cc k :k , :

    (call/cc (lambda (k) (k 1615))) 16158 , . values

    call/cc.

  • 3. : 111

    , call/cc , - : .. - . , . , : - -. . call/cc, , , , .

    3.1.6.

    , . unwind-protect. 9 . :

    (unwind-protect -... )

    , unwind-protect. , -, unwind-protect . prog1 Common Lisp begin0 Scheme, begin, , . unwind-protect , . :

    (let ((a on)) Common Lisp(cons (unwind-protect (list a)

    (setq a off) )a ) ) ((on) . off)

    (block foo(unwind-protect (return-from foo 1)

    (print 2) ) ) 1 ; 2 , -

    . , , . catch block. - , *active-

    9 , car cdr, contentsof the address register contents of the decrement register - IBM 704. , .

  • 3. : 112

    catchers*. unwind-protect, *active-catchers*:

    (define-syntax catch(syntax-rules ()

    ((catch tag . body)(let ((saved-catchers *active-catchers*))

    (unwind-protect(block label

    (set! *active-catchers*(cons (cons tag (lambda (x) (return-from label x)))

    *active-catchers*) ). body )

    (set! *active-catchers* saved-catchers) ) ) ) ) )

    , *active-catchers* - . block catch , catch *active-catchers*, unwind-protect. , : *active-catchers* catch throw, ( ).

    unwind-protect , . -, , . - unwind-protect .10

    , . , , :

    (block foo(unwind-protect (return-from foo 1)

    (return-from foo 2) ) ) ?

    (catch bar(block foo

    (unwind-protect (return-from foo (throw bar 1))(throw something (return-from foo 2)) ) ) ) ?

    , - , , . . -, . - :

    10 unwind-protect Scheme dynamic-wind, [FWH92]; . [Que93c].

  • 3. : 113

    (block bar(unwind-protect (return-from bar 1)

    (block foo ) ) )

    unwind-protect , . (block foo ...). , (block bar ...) 1 . , . - unwind-protect (return-from bar 1) . ( .)

    , . Common Lisp, prog, - tagbody. labels block.[. . 3.3] , , - block, return-from unwind-protect. , call/cc. , call/cc, . , . .

    Scheme , . unwind-protect . , , . - fluid-let:

    (fluid-let ((x )) (let ((tmp x))... ) (set! x )

    (unwind-protect(begin ...)(set! x tmp) ) )

    x ; - x tmp . , x, . , . ,

  • 3. : 114

    () - Common Lisp: fluid-let, , fluid-let., , call/cc. , - Common Lisp.

    3.2. , :

    , . : - . - .

    , , . - ( ), - - .

    3.2.1.

    -, . . - . , - . , , - , . , , .

    , , - , -, , .

    ; - ; , - Common Loops [BKK+86], CLOS [BDG+88] TEO [PNB93]. - - - . : , - .

  • 3. : 115

    define-class :

    (define-class (...) )

    , , . - . make- ; . - , . , set- . . ? , .

    Object, .,

    (define-class continuation Object (k))

    :

    (make-continuation k) ; (continuation-k c) ; (set-continuation-k! c k) ; (continuation? k) ;

    :

    (define-generic ( )[--...])

    ; --- , . , , ; - :

    (define-generic (invoke (f) v* r k)(wrong "Not a function" f r k) )

    invoke, . - , f . f ( f), : wrong.

  • 3. : 116

    define-method - .

    (define-method ( )... )

    define-generic. -, , . , invoke primitive :

    (define-method (invoke (f primitive) v* r k)((primitive-address f) v* r k) )

    - . , - . - , .

    3.2.2.

    evaluate : , -. , , - . , , - , . : x x*. : - - :

    e, et, ec, ef , r

    k, kk v (, , . .)f n

    , . , , .

    (define (evaluate e r k)(if (atom? e)

    (cond ((symbol? e) (evaluate-variable e r k))(else (evaluate-quote e r k)) )

    (case (car e)((quote) (evaluate-quote (cadr e) r k))((if) (evaluate-if (cadr e) (caddr e) (cadddr e) r k))

  • 3. : 117

    ((begin) (evaluate-begin (cdr e) r k))((set!) (evaluate-set! (cadr e) (caddr e) r k))((lambda) (evaluate-lambda (cadr e) (cddr e) r k))(else (evaluate-application (car e) (cdr e) r k)) ) ) )

    : evaluate, invoke resume. , - . - . : lookup update!.

    (define-generic (invoke (f) v* r k)(wrong "Not a function" f r k) )

    (define-generic (resume (k continuation) v)(wrong "Unknown continuation" k) )

    (define-generic (lookup (r environment) n k)(wrong "Not an environment" r n k) )

    (define-generic (update! (r environment) n k v)(wrong "Not an environment" r n k) )

    , , - :

    (define-class value Object ())(define-class environment Object ())(define-class continuation Object (k))

    value, - environment, continuation.

    3.2.3.

    , -:

    (define (evaluate-quotation v r k)(resume k v) )

    3.2.4.

    : , . .

  • 3. : 118

    , , - . - , - . , :

    (define-class if-cont continuation (et ef r))

    (define (evaluate-if ec et ef r k)(evaluate ec r (make-if-cont k et ef r)) )

    (define-method (resume (k if-cont) v)(evaluate (if v (if-cont-et k) (if-cont-ef k))

    (if-cont-r k)(if-cont-k k) ) )

    ec r, . , resume, -. , .11

    3.2.5.

    : .

    (define-class begin-cont continuation (e* r))

    (define (evaluate-begin e* r k)(if (pair? e*)

    (if (pair? (cdr e*))(evaluate (car e*) r (make-begin-cont k e* r))(evaluate (car e*) r k) )

    (resume k empty-begin-value) ) )

    (define-method (resume (k begin-cont) v)(evaluate-begin (cdr (begin-cont-e* k))

    (begin-cont-r k)(begin-cont-k k) ) )

    (begin) (begin ) . begin , (make-begin-cont

    11 , make-if-cont et ef, r; , , k. (if-cont-et k) .

  • 3. : 119

    k e* r). v resume, - .12

    3.2.6.

    . :

    (define-class null-env environment ())(define-class full-env environment (others name))(define-class variable-env full-env (value))

    : null-env variable-env. - name value, others. -, , .

    :

    (define (evaluate-variable n r k)(lookup r n k) )

    (define-method (lookup (r null-env) n k)(wrong "Unknown variable" n r k) )

    (define-method (lookup (r full-env) n k)(lookup (full-env-others r) n k) )

    (define-method (lookup (r variable-env) n k)(if (eqv? n (variable-env-name r))

    (resume k (variable-env-value r))(lookup (variable-env-others r) n k) ) )

    lookup , - : . resume.

    :

    (define-class set!-cont continuation (n r))

    (define (evaluate-set! n e r k)(evaluate e r (make-set!-cont k n r)) )

    12 (cdr (begin-cont-e*k)) resume. , evaluate-begin: (make-begin-cont k (cdr e*) r), . - , , .

  • 3. : 120

    (define-method (resume (k set!-cont) v)(update! (set!-cont-r k) (set!-cont-n k) (set!-cont-k k) v) )

    (define-method (update! (r null-env) n k v)(wrong "Unknown variable" n r k) )

    (define-method (update! (r full-env) n k v)(update! (full-env-others r) n k v) )

    (define-method (update! (r variable-env) n k v)(if (eqv? n (variable-env-name r))

    (begin (set-variable-env-value! r v)(resume k v) )

    (update! (variable-env-others r) n k v) ) )

    , : , . set!-cont -, resume update! , .

    3.2.7.

    , make-function:(define-class function value (variables body env))

    (define (evaluate-lambda n* e* r k)(resume k (make-function n* e* r)) )

    . progn/begin .

    (define-method (invoke (f function) v* r k)(let ((env (extend-env (function-env f)

    (function-variables f)v* )))

    (evaluate-begin (function-body f) env k) ) )

    , - r, . . -, - - , . -, ( , - ) ; , .

  • 3. : 121

    . .

    (define (extend-env env names values)(cond ((and (pair? names) (pair? values))

    (make-variable-env(extend-env env (cdr names) (cdr values))(car names)(car values) ) )

    ((and (null? names) (null? values)) env)((symbol? names) (make-variable-env env names values))(else (wrong "Arity mismatch")) ) )

    . , .

    (define-class evfun-cont continuation (e* r))(define-class apply-cont continuation (f r))(define-class argument-cont continuation (e* r))(define-class gather-cont continuation (v))

    (define (evaluate-application e e* r k)(evaluate e r (make-evfun-cont k e* r)) )

    (define-method (resume (k evfun-cont) f)(evaluate-arguments (evfun-cont-e* k)

    (evfun-cont-r k)(make-apply-cont (evfun-cont-k k) f

    (evfun-cont-r k) ) ) )(define no-more-arguments ())

    (define (evaluate-arguments e* r k)(if (pair? e*)

    (evaluate (car e*) r (make-argument-cont k e* r))(resume k no-more-arguments) ) )

    (define-method (resume (k argument-cont) v)(evaluate-arguments (cdr (argument-cont-e* k))

    (argument-cont-r k)(make-gather-cont (argument-cont-k k) v) ) )

    (define-method (resume (k gather-cont) v*)(resume (gather-cont-k k) (cons (gather-cont-v k) v*)) )

    (define-method (resume (k apply-cont) v)(invoke (apply-cont-f k) v

    (apply-cont-r k)(apply-cont-k k) ) )

  • 3. : 122

    , , . - , evfun-cont. - , - . gather-cont, - .

    , (consfoo bar). foo 33, bar 77. , . k - , r . - cons cons .

    evaluate (cons foo bar) r kevaluate cons r evfun-cont (foo bar) r kresume cons evfun-cont (foo bar) r kevaluate-arguments (foo bar) r apply-cont cons kevaluate foo r argument-cont (foo bar) r apply-cont cons kresume 33 argument-cont (foo bar) r apply-cont cons kevaluate-arguments (bar) r gather-cont 33 apply-cont cons kevaluate bar r argument-cont () r gather-cont 33 apply-cont cons kresume 77 argument-cont () r gather-cont 33 apply-cont cons kevaluate-arguments () r gather-cont 77 gather-cont 33 apply-cont cons kresume ( ) gather-cont 77 gather-cont 33 apply-cont cons kresume (77) gather-cont 33 apply-cont cons kresume (33 77) apply-cont cons kinvoke cons (33 77) k

    3.3. ,

    . 1.7. [. . 45] - car, -, .

    (define-syntax definitial(syntax-rules ()

    ((definitial name)(definitial name void) )

    ((definitial name value)(begin (set! r.init (make-variable-env r.init name value))

    name ) ) ) )

    (define-class primitive value (name address))

  • 3. : 123

    (define-syntax defprimitive(syntax-rules ()

    ((defprimitive name value arity)(definitial name

    (make-primitivename (lambda (v* r k)

    (if (= arity (length v*))(resume k (apply value v*))(wrong "Incorrect arity" name v*) ) ) ) ) ) ) )

    (define r.init (make-null-env))

    (defprimitive cons cons 2)(defprimitive car car 1)

    - invoke, . . : . , , .13 - , . - invoke :

    (define-method (invoke (f primitive) v* r k)((primitive-address f) v* r k) )

    - -. , .

    (define-class bottom-cont continuation (f))

    (define-method (resume (k bottom-cont) v)((bottom-cont-f k) v) )

    (define (chapter3-interpreter)(define (toplevel)

    (evaluate (read)r.init(make-bottom-cont void display) )

    (toplevel) )(toplevel) )

    13 : (begin (set! foo car) (set! car 3) foo) # -, .

  • 3. : 124

    , - - , Smalltalk [GR83], - . - , .

    3.4. call/cc. , :

    , . - -, .

    3.4.1. call/cc

    call/cc k , , invoke, . :

    (definitial call/cc(make-primitivecall/cc(lambda (v* r k)

    (if (= 1 (length v*))(invoke (car v*) (list k) r k)(wrong "Incorrect arity" call/cc v*) ) ) ) )

    , - . call/cc , defprimitive, - k. call/cc ( Lisp1) primitive. , (lambda (v* r k) ...). call/cc . , -. invoke , :

    (define-method (invoke (f continuation) v* r k)(if (= 1 (length v*))

    (resume f (car v*))(wrong "Continuations expect one argument" v* r k) ) )

  • 3. : 125

    3.4.2. catch

    catch - ,