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

欢迎!有关如何工作的更多信息,请参阅关于页面。

0
错误

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

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

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

我认为这可能是一个好的 workaround。

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

这不行,返回 "default"。

奇怪的是,尽管 (symbol quote) 将是无效的,因为 quote 未绑定,但 THIS 通过返回 "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

选中
 
最佳回答

这是根据文档字符串预期的行为,不是 bug。
'foo => (quote foo)
这在读取器中发生,根据case文档字符串,你可以有(常数 常数 常数...),所以这是常数符号的对,即quotefoo

这就是为什么你的在(评估的)表达式'quote上的case'face匹配,因为它是常数表达式的对quoteface

同样地,(symbol quote)是常数表达式symbolquote的对(并且,你的测试表达式同样匹配)。

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

如果从这个说明中还不清楚,那么'quote不合法的原因是这个读取器将其展开为(quote quote),现在你有一个重复的常数表达式。

by
非常棒,感谢你的精彩解释!
by
这不是原始问题的一部分,但重要的是意识到:ClojureScript会在`case`中评估const符号(在“与Clojure的区别”中提及https://script.clojure.org/about/differences)。
...