scheme中的返回函数
我一直在和这个小阴谋家玩耍,在我工作的过程中尝试各种想法(并不是所有的想法都有效)。刚才,我在第6章(在那里他们介绍了助手函数),我觉得一个步骤是可以实现的——我只是不知道如何实现这个步骤 书中的代码如下:scheme中的返回函数,scheme,higher-order-functions,the-little-schemer,Scheme,Higher Order Functions,The Little Schemer,我一直在和这个小阴谋家玩耍,在我工作的过程中尝试各种想法(并不是所有的想法都有效)。刚才,我在第6章(在那里他们介绍了助手函数),我觉得一个步骤是可以实现的——我只是不知道如何实现这个步骤 书中的代码如下: (define (^ b e) (expt b e)) (define (x a b) (* a b)) (define value-i (lambda (nexp) (cond ((atom? nexp) nexp) ((eq? (car (cdr
(define (^ b e) (expt b e))
(define (x a b) (* a b))
(define value-i
(lambda (nexp)
(cond
((atom? nexp) nexp)
((eq? (car (cdr nexp)) '+) (+ (car nexp) (value-i (caddr nexp))))
((eq? (car (cdr nexp)) 'x) (x (car nexp) (value-i (caddr nexp))))
(else
(^ (car nexp) (value-i (caddr nexp))))
)))
定义了以下帮助程序:
(define (operator-i aexp) (car (cdr aexp)))
(define (firstSubExp-i aexp) (car aexp))
(define (secondSubExp aexp) (caddr aexp))
这种简化是:
(define value-i2
(lambda (nexp)
(cond
((atom? nexp) nexp)
((eq? (operator-i nexp) '+) (+ (firstSubExp-i nexp)
(value-i2 (secondSubExp nexp))))
((eq? (operator-i nexp) 'x) (x (firstSubExp-i nexp)
(value-i2 (secondSubExp nexp))))
(else
(eq? (operator-i nexp) '^) (^ (firstSubExp-i nexp)
(value-i2 (secondSubExp nexp))))
)))
我认为我可以看到的简化是,当我们假设所有nexp
都有效时,我们不需要重复((eq?(operator-i nexp)…
样板文件
类似于以下的方法应该可以工作:
(define value-i3
(lambda (nexp)
(cond
((atom? nexp) nexp)
(else
((operator-i nexp)
(firstSubExp-i nexp)
(value-i3 (secondSubExp nexp))))
)))
…除非它没有。它会出错,出现异常:尝试应用非过程…
(+、x和^之一)
我可以看出问题在于,它无法识别我正在尝试使用(operator-I nexp)
调用函数
如何向解释器说明我希望应用从(operator-i nexp)
返回的函数
任何其他提示都是受欢迎的(我使用的是小chez方案)。不幸的是,
value-i3
不起作用,因为(operator-i nexp)
返回一个符号,而不是过程对象。注意'+
和+
之间的区别吗
除了使用列表将符号与程序联系起来(或使用Sylwester的回答中提到的case
或cond
)之外,没有一种简单的方法可以解决这个问题(如果我们排除了eval
,这是一种粗俗和不推荐的做法):
然后使用与Sylvester答案相同的symbol->procedure
如果您发现准文字太难阅读,可以直接使用list
和cons
(define symbol->procedure
(let ((opmap (list (cons '+ +)
(cons 'x x)
(cons '^ ^))))
(lambda (x)
(cond ((assq x opmap) => cdr)
(else #f)))))
OP询问了更多关于
assq
之类的信息,所以我想我应该直接更新帖子返回alist
中的第一个项目,其car
等于key
,或者#f
否则;assq
和assv
类似于assoc
,但使用eq
和eqv?
作为比较运算符。下面是一个示例实现(具有R7RS/SRFI-1语义):
不幸的是,
value-i3
不起作用,因为(operator-i nexp)
返回的是一个符号,而不是过程对象。请注意'+
和+
之间的区别
除了使用列表将符号与程序联系起来(或使用Sylwester的回答中提到的case
或cond
)之外,没有一种简单的方法可以解决这个问题(如果我们排除了eval
,这是一种粗俗和不推荐的做法):
然后使用与Sylvester答案相同的symbol->procedure
如果您发现准文字太难阅读,可以直接使用list
和cons
(define symbol->procedure
(let ((opmap (list (cons '+ +)
(cons 'x x)
(cons '^ ^))))
(lambda (x)
(cond ((assq x opmap) => cdr)
(else #f)))))
OP询问了更多关于
assq
之类的信息,所以我想我应该直接更新帖子返回alist
中的第一个项目,其car
等于key
,或者#f
否则;assq
和assv
类似于assoc
,但使用eq
和eqv?
作为比较运算符。下面是一个示例实现(具有R7RS/SRFI-1语义):
假设的问题是
operator-i
返回一个符号。
当您执行(+1 2)
操作时,+
将被计算到一个过程中,从而使表单可调用。但是,在代码中的运算符位置,结果是符号”+
。然后它尝试应用符号而不是过程。以下是两个操作中的最小示例:
('+ 1 2) ; won't work
(+ 1 2) ; works
当然,您可以在它们之间进行查找:
(define (symbol->procedure sym)
(case sym
((+) +)
((x) x)
((^) ^)
(else #f)))
((symbol->procedure '+) 2 3) ; ==> 5
假设的问题是
operator-i
返回一个符号。
当您执行(+1 2)
操作时,+
将被计算到一个过程中,从而使表单可调用。但是,在代码中的运算符位置,结果是符号”+
。然后它尝试应用符号而不是过程。以下是两个操作中的最小示例:
('+ 1 2) ; won't work
(+ 1 2) ; works
当然,您可以在它们之间进行查找:
(define (symbol->procedure sym)
(case sym
((+) +)
((x) x)
((^) ^)
(else #f)))
((symbol->procedure '+) 2 3) ; ==> 5
对于这个答案,我建议的唯一改变是使用
cond
而不是case
。case
的问题是,它的自动引用形式掩盖了从符号到函数的转换。cond
子句改为:[(eq?sym'+)+]
@JohnClements…不喜欢alist解决方案?它与cond
/case
解决方案一样,不会将符号与过程翻译混淆,而且(在我看来)更简洁@的确,对于那些不熟悉case
的人来说,这并不明显,但它从R2RS开始就存在了,而且所有语法,比如带有附加括号的cond
,如果你以前没有使用过它,看起来都很奇怪。我的意见是case
非常适合这里。@ChrisJester Young-Yep,那一个看起来也不错…th尽管lookup函数使用了太多的内幕方案,但我还是喜欢在函数之外定义a-list,而cond的特殊=>
语法是另一层骗局。@JohnClements感谢您引入术语“内幕方案”;我有。:-D但是是的,我真的不知道有什么好方法可以不用cond
=>来使用assoc
之类的东西。不是这样,就是我必须加入让加和。我对这个答案的唯一建议是使用cond
而不是case
。问题出在哪里对于案例
这里是它的自动报价表obscu