最近我自学MIT 6.5151课程,先读了CS 61AS Unit 0作为准备,然后根据ps0的要求读了SICP 1到2.1(还有相关的讲义)(也根据CS 61A的讲义要求读了2.2.1),然后读了Software Design for Flexibility (SDF) Prologue,第一章和Scheme的部分附录。
我使用 MIT-Scheme。
目前我正在阅读 SDF 第 2 章并做练习 2.5 (b)。
以下代码会产生奇怪的结果,抛出错误“;对象 square 不适用。”和“;对象 (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
,然后将该过程与求值后的操作数一起应用。现在,如果我要制作一个列表,例如,
to-apply
然后(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
你也
list
可以使用 quaiquote 语法:由于数字是自我评估的,因此您不需要取消引用它们,但如果您要使用变量,您也需要在那里执行此操作:-)