1

我对方案很陌生,我对引号和符号不太确定。

这是我的理解:

'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)  <--

编辑2

Eval is Evil 但我想知道它是如何工作的非常重要。

因此,在阅读了 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 显然是邪恶的!

4

2 回答 2

1

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

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

=> 1

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

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

=> 'x
于 2012-11-08T22:25:14.250 回答
1
It's as if unquote was only available from within quote itself.

是的,您只能在带引号的表达式中取消引用,因为只有取消引用才有意义,即您正在引用一个表达式(不想评估表达式中的项目)但想要评估表达式的特定部分,在在这种情况下,您使用 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))))

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

因此你需要使用(f 'a).

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

于 2012-11-09T05:26:52.840 回答