9. Shadows

本章概要:

本章节主要两个方面:

1. 一个计算器的实现(计算算术表达式的值),

   为最后一章节讲解Scheme解释器打基础。

2. church encoding,使用列表来表示数字,

   然后再参照第四章,根据原语函数定义加、减等函数。

9.1. numbered?

判断一个S表达式是否为算术表达式

; numbered?: symbol -> bool
(define numbered?
  (lambda (aexp)
    (cond
     ((atom? aexp) (number? aexp))
     ((or (eq? (car (cdr aexp)) '+)
          (eq? (car (cdr aexp)) '*)
          (eq? (car (cdr aexp)) '^))
      (and (numberd? (car aexp))
           (numberd? (car (cdr (cdr aexp))))))
     (else #f))))

9.2. value

获取一个算术表达式的值

小技巧

; 在Guile环境,请添加如下代码 (define ^ expt)

(define value
  (lambda (nexp)
    (cond
     ((atom? nexp) nexp)
     ((eq? (car nexp) '+)
      (+ (value (cdr nexp))
         (value (cdr (cdr nexp)))))
     ((eq? (car nexp) '*)
      (* (value (cdr nexp))
         (value (cdr (cdr nexp)))))
     (else (^ (value (cdr nexp))
              (value (cdr (cdr nexp))))))))
; 帮助函数
(define 1st-sub-exp
  (lambda (aexp)
    (car (cdr aexp))))

; 帮助函数
(define 2nd-sub-exp
  (lambda (aexp)
    (car (cdr (cdr aexp)))))

; 帮助函数
(define operator
  (lambda (aexp)
    (car aexp)))

(define value
  (lambda (nexp)
    (cond
     ((atom? nexp) nexp)
     ((eq? (operator nexp) '+)
      (+ (value (1st-sub-exp nexp))
         (value (2nd-sub-exp nexp))))
     ((eq? (operator nexp) '*)
      (* (value (1st-sub-exp nexp))
         (value (2nd-sub-exp))))
     (else (^ (value (1st-sub-exp nexp))
              (value (2nd-sub-exp nexp)))))))

使用帮助函数重写的value函数,其实该版本的value函数可以用在前缀、中缀、后缀表达式上,只要修改三个帮助函数即可。

9.3. church encoding

翻译为:邱奇数,关于它的定义详见 Wiki 邱奇数

作者用 () 来表示0, (()) 表示1, (() ()) 表示2... ...

然后定义了对应的原语函数: sero?,edd1,zub1。

  1. sero?: 对应zero?

    (define sero?
      (lambda (n)
        (null? n)))
    
  2. edd1: 对应add1

    (define edd1
      (lambda (n)
        (cons '() n)))
    
  3. zub1: 对应sub1

    (define zub1
      (lambda (n)
        (cdr n)))
    

和第四章一样,根据上面三个原语函数,然后再来定义加、减等这些函数。

(define +
  (lambda (n m)
    (cond
     ((sero? m) n)
     (else (edd1 (+ n (zub1 m)))))))
(define -
  (lambda (n m)
    (cond
     ((sero? m) n)
     (else (- (zub1 n) (zub1 m))))))