Scheme - Lambda作为Bad函数对象

时间:2017-03-13 20:45:31

标签: lambda scheme lisp r5rs

我正在使用Scheme中的metacircular评估器进行家庭作业,我需要允许用户通过将特殊表单添加到表中来安装它们。我们的想法是,当用户输入类似(square 5)的内容时,评估者将查找名为square的表单。如果找到了,它将返回lambda语句,例如(lambda (x) (* x x))

当代码返回lambda语句时,我遇到了问题。我收到以下错误消息:

Error: Bad function object:(lambda (x) (* x x))

真正奇怪的是我可以将参数传递给从我的表中检索的函数,只是我必须先将过程体定义为lambda语句,而不是以{{1开头的列表}}

供参考,这里的代码不起作用。 lambda类似于exp,因此在这种情况下,(install-special-form 'square (lambda (x) (* x x)))评估为namesquare评估为func

(lambda (x) (* x x))

这里有一些有用的代码:

(define (install-eval exp)
  (define name (cadadr exp))
  (define func (caddr exp))
    (if (special-form-lookup (list name func))
        #f
       (begin
         (append! special-forms-table (list name func))
         name)))

我猜测我的问题是,在使用不起作用的代码时,(define (install exp-list) (append! special-forms-table exp-list)) (install (list 'square (lambda (x) (* x x)))) 被评估为引用,而不是实际的lambda?如何获取用户输入以存储可以检索和使用的实际lambda语句?

2 个答案:

答案 0 :(得分:1)

您可能将lambda存储为符号列表,而不是实际过程。这就是为什么这不起作用的原因:

(define f '(lambda (x) (* x x)))
(f 10)
=> Error: Bad function object: (lambda (x) (* x x))

首先尝试评估它:

((eval f) 10)
=> 100

答案 1 :(得分:1)

当您返回列表 (lambda (x) (* x x))时,您无法将其应用于主机,因为它就像执行('(lambda (x) (* x x)) 5)一样。试试吧。你会得到同样的错误。

当Scheme计算特殊形式(lambda (x) (* x x))时,它返回一个封闭对象,其环境为创建时的环境。当你调用它时,它将运行具有该环境的主体,并添加了bingind到x。这需要在您的口译员中进行模拟,因此(lamba (args ...) body)通常会评估为(closure-tag (args ...) environment body)。您的申请需要这些能够在正确的环境中呼叫身体上的eval。奥斯卡建议使用eval从长远来看是行不通的,因为你无法使用eval在解释器中进行闭包,如果你侥幸逃脱,我会认为它是作弊的。