MIT-Scheme实现composex函数遇错误:(unquote f)非标识符问题求助
修复你的Scheme函数组合代码
首先,你遇到的错误是因为lambda参数列表里的逗号——Scheme里参数之间只用空格分隔,逗号是quasiquote(反引号)语法里才会用到的,所以(lambda (ini, f)会被解析成带有(unquote f)的非法结构,这就是报错的原因。除此之外,你的composex逻辑也完全偏离了函数组合的需求,我们一步步来修复:
步骤1:修正语法错误
把lambda参数里的逗号去掉,把(lambda (ini, f)改成(lambda (ini f)——Scheme的参数列表不需要逗号分隔,这是很多其他语言的习惯,在这里会导致语法错误。
步骤2:重构composex的逻辑
函数组合的核心是把前一个函数的输出作为后一个函数的输入,比如f1(f2(f3(x))),需要从最右侧的函数开始,依次把结果传给左边的函数。你的reducex是左折叠函数,但初始值和折叠逻辑都错了:
- 初始值不应该是空列表
'(),而是要传给组合函数的输入x - 折叠函数需要把当前的计算结果传给下一个函数,而不是一直用原始的
x
结合你的reducex,我们可以通过反转函数列表来实现从右到左的应用,修复后的composex如下:
(define (composex funcs) (lambda (x) (reducex x (lambda (current-result func) (func current-result)) (reverse funcs))))
完整修复后的代码
把所有错误修正后,完整代码如下:
(define (reducex initial f arr) (if (null? arr) initial (reducex (f initial (car arr)) f (cdr arr)))) (define (abst x) (if (< x 0) (- x) x)) (define (mult2 x) (* x 2)) (define (composex funcs) (lambda (x) (reducex x (lambda (current func) (func current)) (reverse funcs)))) (define absmult2 (composex (cons abst (cons mult2 '())))) (absmult2 2) ; 输出 4 (absmult2 -2) ; 输出 4
额外优化:不用反转列表的实现
如果不想反转列表,可以写一个右折叠的reduce函数,直接从列表末尾开始处理,这样更符合函数组合的直观逻辑:
(define (reduce-right initial f arr) (if (null? arr) initial (f (car arr) (reduce-right initial f (cdr arr))))) (define (composex funcs) (lambda (x) (reduce-right x (lambda (func result) (func result)) funcs)))
这个版本的composex不需要反转列表,reduce-right会先递归处理列表的最后一个函数,再把结果传给前一个函数,完美实现f1(f2(f3(x)))的效果。
内容的提问来源于stack exchange,提问作者Ayush Goel
相关产品推荐
相关产品推荐

