The Scheme Programming Language 读书笔记,chapter 4.

Chapter 4. Procedures and Variable Bindings

执行诀和变量绑定是Scheme程序的两大基石。

Section 4.1. Variable References

变量绑定通常由define,lambda,let等等语法形式创建的。一个标识符被当作表达式的时候,如果相关的变量绑定存在,那么这个标识符则被当作一个变量。

如果在library形式或者顶层程序引用了某个标识符,并且相应的变量绑定不存在,那么这是一个语法上的错误。它们必须指定一个变量,关键字,记录名,或者其他实体。下面的代码在语法上是错误的:

(define q (g 3))
(define g
  (lambda (x)
    (+ x x))

但是如果实际的引用出现在定义之后,则是可以的。

(define f
  (lambda (x)
    (g x)))
(define g
  (lambda (x)
    (+ x x)))

Section 4.2. Lambda

lambda语法形式用来执行诀。任何创建执行诀或者创建局部变量绑定的操作最终都是通过lambda或者case-lambda定义的。

The body may begin with a sequence of definitions, 这句话不太了解。

当执行诀创建的时候,除了形参之外,之内那些自由性的变量绑定会被留存在执行诀内部。但执行诀施用的时候,形参会绑定到实参,留存的变量绑定会被复原,内容被执行。

关于形参绑定的三种形式,前面章节已经介绍过了。当执行的时候,执行诀包含的表达式会被逐条执行,并返回最后一条表达式的结果。

Section 4.3. Case-Lambda

case-lambda创建的执行诀可以接受可选参数。其形式是:(case-lambda clause ...)。也就是可以接受多个clause,每个clause的形式是:[formals body1 body2 ...]

当case-lambda被调用的是,会按顺序查看各个clause,找到第一个参数个书匹配的clause执行。如果没有能够匹配成功,那么会报告&assertion类型的异常。

下面是一个例子:

(define make-list
  (case-lambda
    [(n) (make-list n #f)]
    [(n x)
     (do ([n n (- n 1)] [ls '() (cons x ls)])
       ((zero? n) ls))]))

Section 4.4. Local Binding

let语法形式(let ((var expr) ...) body1 body2 ...)用来创建局部变量绑定。

典型的let的语法定义:

(define-syntax let
  (syntax-rules ()
    [(_ ((x e) ...) b1 b2 ...)
     ((lambda (x ...) b1 b2 ...) e ...)]))

此外由let*,跟let功能类似,不过其变量绑定的时候是按左到右求值。

let*可以由嵌套的let定义:

(define-syntax let*
  (syntax-rules ()
    [(_ () e1 e2 ...)
     (let () e1 e2 ...)]
    [(_ ((x1 v1) (x2 v2) ...) e1 e2 ...)
     (let ((x1 v1))
       (let* ((x2 v2) ...) e1 e2 ...))]))

letrec,形式为(letrec ((var expr) ...) body1 body2 ...),和前面的let和let*类似,不过变量绑定的时候允许互相调用:

(letrec ([sum (lambda (x)
		(if (zero? x)
		  0
		  (+ x (sum (- x 1)))))])

对于letrec的另一个限制是其expr不能返回两次。

letrec适用在((var expr) ...) 的expr…有循环引用的情况下。在需要从左到右对expr…求值的时候,使用letrec*。

letrec的语法形式的一种定义:

(let ((var #f) ...)
  (let ((temp expr) ...)
    (set! var temp) ...
    (let () body1 body2 ...)))

letrec*的语法形式的一种定义:

(let ((var #f) ...)
  (set! var expr) ...
  (let () body1 body2 ...))

Section 4.5. Multiple Values

let-value以及let*-values可以方便得同时制造多个变量绑定,例子如下:

(let-values ([(a b) (values 1 2)] [c (values 1 2 3)])
  (list a b c))
(let*-values ([(a b) (values 1 2)] [(a b) (values b a)])
  (list a b))

Section 4.6. Variable Definitions

有以下几种语法形式:

(define var expr)
(define var)
(define (var0 var1 ...) body1 body2 ...)
(define (var0 . varr) body1 body2 ...)
(define (var0 var1 var2 ... . varr) body1 body2 ...)

对于(define var expr),其expr不能返回多次。

对于(define var),其绑定的值是未定义的。

剩下的形式,是为了方便创建执行诀。

Section 4.7. Assignment

简单说,就是(set! var expr)。用于更改一个既有变量绑定的内容。

(本篇完)