2024 Clojure 状况调查! 中分享您的想法。

欢迎!请查看 关于 页面了解更多关于本站的信息。

0
错误

我在实现一个小型的 Lisp 解释器,这让我发现了 case 实现中的这个问题。

(case "s"
  'quote "quote"
  "default")

;; Syntax error macroexpanding case at (org:localhost:56082(clj)*:131:16).
;; Duplicate case test constant: quote

我认为这可能是一个好的解决方案

(case 'quote
  (symbol "quote") "quote"
  "default")
;; => "default"

但这不起作用,它返回 "default"。

奇怪的是,尽管 (symbol quote) 会是无效的,因为 quote 未绑定,但这次的返回值是 "quote",看起来似乎可以工作。

(case 'quote
  (symbol quote) "quote"
  "default")
;; => "quote"

非常奇怪。看看这个。我们尝试一下 'face 的例子。它会返回什么?

(case 'quote
  'face "face"
  "default")
;; => "face"

它匹配 'quote

实际上,任何被引用的对象都匹配。

(case 'quote
  (quote 123) "123"
  "default")
;; => "123"

希望这足以让了解 case 宏展开的人明白。

感谢!

1 个答案

+1

被选中
 
最佳答案

这是按照文档字符串的预期行为,不是错误。
'foo => (quote foo)
在读取器中出现这种情况,并且根据 case 的文档字符串,你可以有 (constant constant constant...),所以这是常数符号 Pair quotefoo

这就是为什么你在对 (evaluated) 表达式 'quotecase 上匹配到了 'face,因为它是由常数表达式 Pair quoteface 组成的。

同样,(符号引号)是常数表达式对symbolquote(且你的测试表达式也匹配。

根据文档字符串:"测试常量不会被评估。它们必须是编译时字面量,并且不需要引用。"

如果不清楚,'quote不合法的原因是读者将此扩展为(quote quote),现在你有一个重复的常数表达式。

太棒了,谢谢您的精彩解释!
这并不属于原始问题的一部分,但重要的是要注意:ClojureScript在`case`中评估常量符号(在“与Clojure的差异”中提及https://script.clojure.org/about/differences)。
...