计划什么是符号,并评估它们

时间:2012-11-08 22:19:52

标签: scheme symbols

我对计划很陌生,我对引号和符号的确不太确定。

以下是我的理解:

'a
-> a

'()
->(list)

'(1 2 3)
(list 1 2 3)

'(1 . 2)
(cons 1 2)

''a
(quote a)

So:

'(1 . 'a)
(1 quote a) => (list 1 quote a)

我想要实现的目标如下。

((let ((x 1) (y 2)) 
  (lambda(f) ,f)) 'x)
-> 1

我向该函数发送一个符号,该符号应该被评估为当前范围,在这种情况下将返回1.

相反,我有这个错误:

*** ERROR IN #<procedure #4>, (console)@243.32 -- Unbound variable: unquote

就好像unquote只能从quote内部获得。

修改

我刚刚阅读了一些文档并找到了函数:“eval”似乎正在寻找我想要的东西。

(define a 'foobar)
(define foobar 2)
(eval a)
-> 2

(define a 'x)
(define f (let ((x 1) (y 2)) 
 (lambda (h) (eval h))))
(f a)
*** ERROR -- Unbound variable: y
(f y)
*** ERROR IN (console)@278.4 -- Unbound variable: y

但我不确定是否理解。

这是鸡的堆栈跟踪

Error: unbound variable: x

    Call history:

    <syntax>      (f (quote x))
    <syntax>      (quote x)
    <syntax>      (##core#quote x)
    <eval>    (f (quote x))
    <eval>    (eval h)  <--

EDIT2

Eval是邪恶的,但我想知道它是如何工作的非常重要。

因此,在阅读了Ankur的答案之后,我非常确定这是一个范围问题而且实际上是它。所以根据我的理解,似乎eval可能试图用“全局”来评估任何东西。

> (define a 11)
> (define b 'a)
> (eval b)
11
> (let ((a 10)) (eval b))
11
> (let* ((a 10) (b 'a)) (eval b))
11
> (let* ((a 10) (b 'a)) b)       
a
> (let* ((c 10) (d 'c)) d)
c
> (let* ((c 10) (d 'c)) (eval d))
*** ERROR -- Unbound variable: c
计划中的Eval显然是邪恶的!

2 个答案:

答案 0 :(得分:1)

特别是对于这种情况,您不需要引用要评估的表达式,这将起作用:

(let ((x 1) (y 2)) 
  ((lambda (f) f) x))

=> 1

在问题的代码中,请注意变量x仅存在于定义它的let范围内;最外面的'x符号只是一个与x表达式中let无关的符号:

((let ((x 1) (y 2)) 
   (lambda (f) f)) 'x)

=> 'x

答案 1 :(得分:1)

It's as if unquote was only available from within quote itself.

是的,你只能在引用的表达式中进行取消引用,因为只有unquoting是有意义的,即你引用一个表达式(不想评估表达式中的项)但是希望表达式的特定部分是评估,在这种情况下,你使用unquote。

(define a 10)
`(a b ,a) ==> '(a b 10)

在最后一个表达式中,我希望a和b不被评估,但第三个元素,即a应该被评估并被其值替换,因此我们使用unquote。

您的代码:

(define f (let ((x 1) (y 2)) 
 (lambda (h) (eval h))))

f的参数必须是未评估的表达式,因为参数h是使用eval计算的。

因此您需要使用(f 'a)

注意:(f 'y)不起作用,因为使用let创建的y的范围消失了。