2024 年 Clojure 状态调查! 分享您的想法。

欢迎!请查看 关于 页面以了解更多关于该页面如何工作。

+1
语法和读取器

如果一个 data-reader 返回 nil,读取器将抛出 java.lang.RuntimeException:没有分派宏... 错误消息表明的第一个字符的标签没有分派宏。

这里有一个简单的例子

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

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

RuntimeException 没有分派宏:f clojure.lang.Util.runtimeException (Util.java:219)
`

原始的读取器代码没有区分 data-reader 的不存在与从合适的 data-reader 返回的 nil 值。因此它感到困惑,并试图找到一个分派宏,将其推送到错误的代码路径,最终产生一个误导性的错误信息。

原始文档没有区分 nil作为一个非法值。显然,这个错误是原始 data-reader 代码中的疏忽,而不是一个故意的功能。

补丁使用哨兵值来区分缺少数据读取器的情况和返回 nil 值的情况。

补丁: clj-1139-2.patch

15 个答案

0

由:[email protected] 发表的评论

clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 允许 data-reader 返回 nil 而不是抛出异常。对可能存在的标签或记录执行卫生检查。为可能实际上是分派宏的特殊字符提供更好的错误信息(而不是假设它是标记字面量)。

0

由:[email protected] 发表的评论

clj-1138-data-reader-return-nil-for-no-op.patch 允许将返回 nil 的数据读取器视为无操作(类似 #_)。nil 通常不是一个有用的值(实际上它会导致 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 来解决原始问题。该表达式 conveniently 评估为 nil,因此您可以在需要时得到 nil。这也适用于应用补丁之后,因此如果您确实想返回 nil,仍然有这种方法。

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

评论者:jafingerhut

clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 于 2012 年 12 月 22 日的补丁,如果使用以下命令,仍可干净地应用到最新的 master 上

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

如果没有 --ignore-whitespace 选项,补丁会失败,因为 Clojure master 最近更改了一些空白。

0

评论者:jafingerhut

好的,现在使用最新的 master(此时为 1.5.0-RC15),如果使用以上 “git am” 命令,clj-1138-allow-data-reader-to-return-nil-instead-of-throwing.patch 不再干净地应用。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] 发表的评论

如果问题不明确,我会问为什么nil返回值会专门针对data-reader处理?并且如果它被认为是设计上的非法,这个错误消息是否能让用户受益?

我在提交错误时没能找到任何文档化的限制,今天也没有。因此,这在我看来像是一个简单的错误。data-reader应该允许返回nil,Clojure reader应该像平常一样处理nil。我的解决方案是返回(quote nil),这提供了所需的行为而不会触发错误。

0

评论者:alexmiller

期待更详细的描述更新。我的问题是调用data reader函数是否应该返回nil。有没有什么好的用例需要这样?您似乎是使用reader读取非nil标记值,因此返回nil令人困惑。这不可能进行双向转换,因此似乎是不对称的。

0
评论者:[email protected]

没有法律惩罚,我就应该能够这样做。我的简单例子是{{#C NULL}},这对我来说显然是nil。

回顾这个问题,我发现大多数人认为插入符字面量是把外来的值编码在Clojure字面量中的方法。如果你只关心一种扩展数据表示法,谁还需要另一种写nil的方法呢?这是一个公平的问题。

我想使用数据读取器作为某种受限的读取宏(如Common Lisp中使用)。我在做平台特定的工作时发现了这个错误(在实现读取器条件之前很久)。在我这种情况中,在“其他”平台上返回nil很方便。

数据读取器的许多用法不是双射的。例如,将{{#infix (3 + 4)}}解释为常量7,也同样不是往返的。除非你是Dan Friedman或Wil Byrd,否则往返验证是一个难题。:-)

我将尝试用更多的上下文更新我的描述,但我不想让任何人因为我的非传统用法而分散精力,关注明显的错误(和糟糕的错误消息)。
0

由:[email protected] 发表的评论

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

0
评论者:[email protected]

我已经测试了这个补丁,并且它在我的当前主版本上工作得很好。我建议添加另一个测试来确认edn/read-string也正确工作。这是我用过的东西。这也测试了覆盖默认读取器是否生效。如果您想使用该测试,请随时使用。


(deftest clj-1138-uuid-override
  (is (nil? (binding [*data-readers* {'uuid (constantly nil)}]
              (read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\""))))
  (is (nil? (edn/read-string {:readers {'uuid (constantly nil)}}
                             "#uuid \"550e8400-e29b-41d4-a716-446655440000\""))))

0
...