Closed asukaminato0721 closed 2 years ago
这段代码是照着黑板敲的
#lang sicp
(define (diff expr var)
(cond ((constant? expr var) 0)
((same-var? expr var) 1 )
((sum? expr var) (make-sum (diff (a1 expr) var)
(diff (a2 expr) var))
)
((product? expr var) (make-sum (make-product (m1 expr )(diff (m2 expr) var))
(make-product (m2 expr )(diff (m1 expr) var))
)
)
)
)
(define (constant? exp var)
(and (atom? exp)
(not (eq? exp var)))
)
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
;https://stackoverflow.com/questions/16932619/why-am-i-getting-an-unbound-error-for-atom
(define (same-var? expr var)
(and (atom? expr)
(eq? expr var)))
(define (sum? exp var)
(and (atom? exp)
(eq? (car exp) '+) )
)
(define (product? exp var)
(and (not (atom? exp))
(eq? (car exp) '*) )
)
(define (make-sum a1 a2)
'('+ a1 a2)
)
(define (make-product m1 m2)
(list '* m1 m2)
)
(define a1 cadr)
(define a2 caddr)
(define m1 cadr)
(define m2 caddr)
(define foo '(+ a x 1))
(diff foo 'x)
没报错,但是 DrRacket 没有输出。
另外 Telegram,QQ 搜了一圈,没有群组。感觉 Racket 有点小众(或者我应该搜索 Lisp?)
已搜到 SICP 群组
QQ 群的 Noah.ss
给了答复
sum? make-sum make-product 的定义似乎都有问题,另外 diff 处理的表达式应该是只有三个项的列表。
建议 a1 a2 m1 m2 不要直接定义成 c*r 最好用lambda包装一下。
#lang sicp
(define (diff expr var)
(cond [(constant? expr var) 0]
[(same-var? expr var) 1]
[(sum? expr var)
(make-sum (diff (a1 expr) var)
(diff (a2 expr) var))]
[(product? expr var)
(make-sum (make-product (m1 expr) (diff (m2 expr) var))
(make-product (m2 expr) (diff (m1 expr) var)))]))
(define (constant? exp var)
(and (atom? exp)
(not (eq? exp var))))
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
;; https://stackoverflow.com/questions/16932619/why-am-i-getting-an-unbound-error-for-atom
(define (same-var? expr var)
(and (atom? expr)
(eq? expr var)))
(define (sum? exp var)
(and (not (atom? exp))
(eq? (car exp) '+)))
(define (product? exp var)
(and (not (atom? exp))
(eq? (car exp) '*)))
(define (make-sum a1 a2)
(list '+ a1 a2))
(define (make-product m1 m2)
(list '* m1 m2))
(define (a1 expr) (cadr expr))
(define (a2 expr) (caddr expr))
(define (m1 expr) (cadr expr))
(define (m2 expr) (caddr expr))
(display (diff '(+ a x) 'x))
(newline)
(display (diff 'x 'x))
(newline)
(display (diff 9 'x))
(newline)
如果有任何问题,欢迎提问哦!虽然我没有看群里面的解答,还是为没有明白的同学简单解释一下:
'
符号构造列表时,内部使用字面量即可。下面是你的代码,(define (make-sum a1 a2)
'('+ a1 a2) )
请仔细对比以下三条条表达式的结果:
> [eq? (car '('+ 1 2 3)) '+]
#f
> [eq? (car '(+ 1 2 3)) '+]
#t
; 如果想要使用第一条表达式的思路写,那么就要使用准引用(quasi-quote)
> [eq? (car `(,'+ 1 2 3)) '+]
#t
diff
时,例如这里的 '(+ a x 1)
,实际上是 (+ . (a . (x . (1 . '()))))
,会被归约(reduce)为 (diff (+ . (a . (x . (1 . '())))) 'x)
=> (+ (diff a 'x) (diff (x . (1 . '())) 'x))
其中,(diff (x . (1 . '())) 'x)
的待求导表达式缺少运算符,实际上是不会被 diff
的 cond
语句选中的,你可以在 cond
子句中添加一个 else
分支,在该分支抛出一个错误试试。
看起来没这个 issue,我就自己建了一个,如有冒犯可以 close