scheme中的返回函数

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

我一直在和这个小阴谋家玩耍,在我工作的过程中尝试各种想法(并不是所有的想法都有效)。刚才,我在第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 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