2024年Clojure调查问卷中分享你的想法!

欢迎!请查阅关于页面以了解更多此工作如何运作的信息。

+1
语法和读取器

如果数据读取器返回null,读取器将抛出java.lang.RuntimeException: No dispatch macro... 错误信息意味着没有为标签的第一个字符found相应的分发宏。

这里有一个简单的例子

`
user=> (binding [*data-readers* {'f/ignore (constantly nil)}]

     (read-string "#f/ignore 42 10"))

RuntimeException No dispatch macro for: f clojure.lang.Util.runtimeException (Util.java:219)
`

原始的读取器代码没有区分没有数据读取器和适当的数据读取器返回null的情况。因此,它感到困惑并试图查找分发宏,导致了错误代码路径的进一步错误,并最终产生了误导性错误信息。

原始文档未将null视为非法值。显然,这个bug是原始数据读取器代码中的疏忽,而不是故意功能。

这个补丁使用哨兵值来区分缺少数据读取器的情况与返回null值的情况。

补丁: clj-1139-2.patch

15 个答案

0

评论由:[email protected]作出

clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 允许数据读取器返回null而不是抛出异常。对可能的标签或记录进行sanity检查。对于可能是分发宏的特殊字符,提供了更好的错误信息(而不是假设它是一个标籤字面量)。

0

评论由:[email protected]作出

clj-1138-data-reader-return-nil-for-no-op.patch 允许返回null的数据读取器在读取器中被视为空操作(如#_)。通常,对于数据读取器返回null不是一个有用的值(实际上,在Clojure 1.4至1.5 beta2中引发异常)。使用这个补丁,可以使用数据读取器实现有条件的功能读取器。

0

评论由:[email protected]作出

clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 是第一个要考虑的补丁。它仅仅允许数据读取器返回 nil 作为值,并将 nil 作为最终值返回。我认为它实现了最初为分发宏设计的意图,并在许多情况下(主要是打字错误)提供了更好的错误信息。

第二个补丁 clj-1138-data-reader-return-nil-for-no-op.patch 依赖于先应用其他补丁。它采取额外一步,将数据读取器返回的 nil 值视为读取器的无操作(类似于 #_)。

0

评论由:[email protected]作出

实际上,你可以通过让你的数据读取器返回 '(quote nil)' 而不是纯 nil 来解决这个问题。该表达式方便地进行求值,因此可以在必要时获取 nil。在应用补丁后,这仍然是可以返回 nil 的方法。

(binding (link: *data-readers* {'x/nil (constantly '(quote nil))}) (read-string "#x/nil 42"))
;=> (quote nil)
0

评论作者:jafingerhut

如果使用以下命令,则带有日期 2012-12-22 的补丁 clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 仍然可以干净地应用到最新主分支上

% git am --keep-cr -s --ignore-whitespace < clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch

如果没有 --ignore-whitespace 选项,补丁将会失败,仅因为 Clojure 主分支最近更改了一些空白字符。

0

评论作者:jafingerhut

好的,现在使用最新主分支(此时为 1.5.0-RC15),补丁 clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 无法干净地应用,即使使用上面给出的 'git am' 命令中的 '--ignore-whitespace' 选项。Steve,如果你能看出需要更新什么,那将非常棒。在 "http://dev.clojure.org/display/design/JIRA workflow" 的 "Updating stale patches" 部分中建议使用补丁命令还不够,可能需要仔细人工检查以查看需要更新什么。

0

评论由:[email protected]作出

我已经删除了我的补丁。LispReader 和新 EdnReader 最近发生了一些变化。

0

评论人:alexmiller

修复了空格警告,并更新了补丁,使其生效,没有语义变化,在 clj-1139-2.patch 中保留了归属权。

0

评论人:alexmiller

票据需要更好地描述问题和在补丁中采用的方法。

0

评论由:[email protected]作出

如果问题不明确,我就会问为什么data-reader返回nil应该被特殊处理?如果它是设计上的非法操作,这个错误消息是否能启发用户?

当我提交这个bug时,我没有发现任何记录的限制,到今天我还是没有发现。所以我认为这只是一个简单的bug。data-reader应该允许返回nil,Clojure reader应该像通常一样处理nil。我的临时解决方案是返回(quote nil),这样在不会触发bug的情况下得到了预期的行为。

0

评论人:alexmiller

希望看到更多的描述更新。我的问题是调用数据读取器函数是否应该返回nil。有什么好的用例需要这样吗?看起来你正在使用读取器读取非nil标签值的描述,因此返回nil会让人困惑。这样可能不是双向可转换的,因此看起来是不对称的。

0
评论人:[email protected]

没有法律规定不得犯罪,也就是说,除非你声明这是非法的,否则我可以这样做。我的简单示例是{{#C NULL}},在我看来这显然是nil。

回顾这个问题,我可以看出大多数人认为tagged literals是一种在Clojure字面量中编码外部值的方法。如果你只关心可扩展的数据表示,为什么还需要另一种编写nil的方法呢?这是一个很合理的问题。

我想将data-readers作为某种受限制的读取宏(如Common Lisp中使用的)使用。在我做平台特定的事情时发现了这个bug(在实现读取器条件之前很久)。在我的情况下,在“其他”平台上返回nil是很方便的。

许多数据读取器的使用不是双射的。例如,将“(3+4)”解释为常数7也不是可逆的。除非你是Dan Friedman或Wil Byrd,双向可逆是一个非常严格的约束。:-)

我会试图用更多上下文更新我的描述,但我不想因为我不寻常的使用而分散人们对明显错误的注意(和糟糕的错误信息)。
0
by

评论由:[email protected]作出

顺便说一句,这个错误是CLJ-1138,但提出的补丁说“1139”,这可能会让一些忙碌的审阅者感到困惑。

0
by
评论人:[email protected]

我对补丁进行了测试,并发现它在我的当前master版本上运行良好。我建议添加另一个测试来确认edn/read-string也能正确工作。这是我所使用的。这也测试了覆盖默认读取器的工作。如果您需要,请随意使用这个测试。


(deftest clj-1138-uuid-override
  (is (nil? (binding [*data-readers* {'uuid (constantly nil)}]
                                                         
  (is (nil? (edn/read-string {:readers {'uuid (constantly nil)}}
                                                         

0
by
...