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)
这发生在Reader中,根据case文档字符串,您可以有(constant constant constant...),因此这是常量符号的对,即quotefoo

这就是为什么您的case在表达式'quote上与'face匹配,因为它是由常数表达式quoteface组成的成对。

类似地,(symbol quote)是由常数表达式symbolquote组成的成对(并且,同样,您的测试表达式与此匹配)。

文档字符串中写道:“测试常量不会被求值。它们必须是编译时字面量,并且不需要引用。”

如果不清楚,'quote不合法的原因是因为读取器将其扩展为(quote quote),现在您具有重复的常数表达式。

by
真是太好了,感谢您精彩的解释!
by
这与原始问题无关,但重要的是要意识到, ClojureScript在`case`中求值const符号(在“与Clojure的差异”中有提及 https://script.clojure.org/about/differences)。
...