请在2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多关于如何使用此网站的信息。

+1
语法和reader

如果一个data-reader返回nil,reader会抛出java.lang.RuntimeException: No dispatch macro... 错误消息暗示,对于标签的第一个字符 whatever,没有相应的dispatch宏。

以下是一个简单的示例

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

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

RuntimeException: 没有找到派发宏为: f clojure.lang.Util.runtimeException (Util.java:219)
`

原始的reader代码没有区分没有data-reader和合适的data-reader返回nil的情况。因此,它变得困惑,试图找到一个派发宏,将其引向错误的代码路径,最后产生了一个误导性的错误消息。

原始的文档没有将nil视为非法值。显然,这个错误是在原始data-reader代码中的一次疏忽,而不是一个有意引入的功能。

这个修改使用了一个哨兵值来区分缺失的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而不是抛出异常。它会进行智力检查,以确保可能的标签或记录是Java标识符开头。对于可能是派发宏的特殊字符给出更好的错误消息(而不是假设它是标记字面量)。

0

评论者为:[email protected]

clj-1138-data-reader-return-nil-for-no-op.patch 允许返回nil的data-reader被reader作为no-op处理(如#_)。nil通常对于data-reader返回不是一个有用的值(它在Clojure 1.4到1.5 beta2版本中实际上会导致异常)。通过这个补丁,可以使用data-readers实现类似条件功能阅读器的东西。

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 值视为读取器的一个无操作(no-op)(像 #_)。

0

评论者为:[email protected]

实际上,你可以通过让你的数据读取器返回 '(quote nil)' 而不是普通的 nil 来解决原始问题。这个表达式可以方便地评估为 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

OK,现在使用最新的 master(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
by

评论者:alexmiller

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

0
by

评论者:alexmiller

工单需要更好的问题描述和补丁中采用的方法。

0
by

评论者为:[email protected]

如果问题不清楚,我会问为什么 nil 返回值被特别对待以用于数据读取器?如果按照设计被认为是非法的,这个错误信息是否能让用户得到启发?

在提交错误时,我没有找到任何文档化的限制,今天仍未找到。所以这对我来说似乎是一个非常简单的错误。数据读取器应该允许返回 nil,Clojure 读取器应该像通常一样处理 nil。我的解决方案是返回 (quote nil),这样就可以得到预期的行为而不触发错误。

0
by

评论者:alexmiller

我希望能够更新描述。我的问题是调用数据读取器函数是否应始终返回 nil。有什么好的用例需要这样做?它似乎是在读取标记值时得到的 nil,这很令人困惑。这不可能完全可逆,因此似乎是不对称的。

0
by
评论者:[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]

我测试了这个补丁,它在我当前的master版本上工作得很好。我建议添加另一个测试来确认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
...