我对计划很陌生,我对引号和符号的确不太确定。
以下是我的理解:
'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显然是邪恶的!
答案 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的范围消失了。