我不是计划专家所以不确定我是否在这里使用正确的术语。让代码说明一切:
CSI> (define tree '(1 2 3 'Symb 4 5 6))
#<unspecified>
CSI> tree
(1 2 3 (quote Symb) 4 5 6)
CSI> (symbol? 'Symb)
#t
CSI> (map symbol? tree)
(#f #f #f #f #f #f #f)
来自Clojure背景,我认为在Scheme中使用符号就像Clojure中的关键字一样。我应该通过嵌套列表结构并用函数调用替换符号。这是我的一维解决方案,它确实有效:
(define (print-track track attrs)
(apply fmt #t
(map (lambda (attr)
(cond
((symbol? attr) (get-attr attr track))
(else attr)))
attrs)))
(symbol?)
行上方的空白区域是(list?)
有条件的,但这可能是错误的方法。
我正在使用Chicken Scheme。
答案 0 :(得分:18)
你遇到了Lisp引用“gotcha”。在Scheme中,符号用于变量引用,您显然可以理解。评估为true:
> (symbol? 'Symb)
因为您引用了该符号,并阻止将其用作变量引用。
> (symbol? Symb)
首先查找Symb变量的值,然后检查该值是否为符号。
> (let ((Symb 'foo)) (symbol? Symb))
将评估为#t,因为Symb的值是符号:foo。
> (let ((Symb 7)) (symbol? Symb))
当然会评估为#f。
你似乎惹恼了引用的细微差别。
'Symb
实际上是速记;它相当于
(quote Symbol)
再次返回其未评估的论点。
但是你的代码不需要内部引用。当你
> (define tree '(1 2 3 'Symb 4 5 6))
引用整个列表;将会评估列表中的 nothing 。这就是为什么
> tree ; => (1 2 3 (quote Symb) 4 5 6)
在引用列表中,'Symb等同于(引用Symb),这实际上是一个列表。由于引用了整个列表,因此使用Symb未引用不会被视为变量引用。它只是符号。
> (define tree '(1 2 3 Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)
现在,如果您将所有这些参数传递给list函数,那么您最初所做的就是正确的:
> (define tree (list 1 2 3 'Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)
在这种情况下,您将这些参数传递给函数;函数的参数被计算,因此您需要引用以防止符号被视为变量引用。
> (define tree (list 1 2 3 (quote Symb) 4 5 6))
会做同样的事情。