最近自学MIT 6.5151课程时,先看了CS 61AS Unit 0作为准备。然后我按照ps0的要求阅读了SICP 1到2.1(以及相关的讲义)(也按照CS 61A笔记的要求阅读了2.2.1),然后软件灵活性设计(SDF)序言,第1章和部分内容方案附录。
我使用 MIT-Scheme。
目前我正在阅读 SDF 第 2 章并做练习 2.5 (b)。
以下代码有奇怪的结果,抛出错误“;对象方块不适用。”和“;对象 (lambda (x) (square x)) 不适用。”。这里
func_polynomial_minimal_unit
在调用 (f(f(g(x)))
时会计算类似
(func_polynomial_minimal_unit '((f . 2) (g . 1)))
的内容
(define (compose f g)
(define (the-composition . args)
(call-with-values (lambda () (apply g args))
f))
the-composition)
(define (iterate n)
(define (the-iterator f)
(if (= n 0)
identity
(compose f ((iterate (- n 1)) f))))
the-iterator)
(define (identity x) x)
(define (func_polynomial_minimal_unit . func_pow_pair_lst)
(if (null? (car func_pow_pair_lst)) ; contain one null pair
identity
(let ((cur_func_pow (caar func_pow_pair_lst)))
(newline)
(display cur_func_pow)
(compose
((iterate (cdr cur_func_pow)) (car cur_func_pow))
(func_polynomial_minimal_unit (cdr func_pow_pair_lst))))))
;; equivalent lambda for the following `func_polynomial_minimal_unit`.
((lambda (x) (expt (* x 9) (expt 2 3))) 3)
;; these works
((compose ((iterate 3) (lambda (x) (square x))) (lambda (x) (* 3 x))) 3)
((compose ((iterate 3) square) (lambda (x) (* 3 x))) 3)
;; these doesn't work
((func_polynomial_minimal_unit '((square . 3) ((lambda (x) (* 3 x)) . 2))) 3)
((func_polynomial_minimal_unit '(((lambda (x) (square x)) . 3) ((lambda (x) (* 3 x)) . 2))) 3)
但如上面的代码所示,这些过程是可以应用的。那么为什么会抛出这些错误呢?
符号和变量是不同的东西。代码中的裸符号是变量(或类似
let
的语法),引用列表中的相同符号只是与变量 square
或变量 a
无关的符号
当您编写像
(square a)
这样的代码时,Scheme 会计算运算符,即变量 square
。由于它评估一个过程,因此它评估变量 a
,然后将过程与评估的操作数一起应用。
现在,如果我要列出一个清单,例如。像
(define to-apply '(square a)))
一样应用,然后尝试打印这个(display to-apply)
,你会看到与你写的完全相同的内容,因为你引用了它。 (apply (car to-apply) (cdr to-apply)) 将为您提供与您遇到的完全相同的错误消息,因为符号 square
不是一个过程。
但是,如果您将其定义为
(define to-apply (list square a)))
然后执行 (display to-apply)
,您会看到类似 (#<procedure-suqare> 3)
的内容,并且 (apply (car to-apply) (cdr to-apply))
会给您 9