Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

15 Feb 2021

The Scheme Programming Language读书笔记【三】

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)。用于更改一个既有变量绑定的内容。

(本篇完)

Categories

Tags