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

欢迎!请参阅关于页面了解更多关于此功能的信息。

0
打印

user=> (read-string (pr-str {(keyword "key@other") :stuff}))
RuntimeException Map 字面量必须包含偶数个形式  clojure.lang.Util.runtimeException (Util.java:170)


pr-str 输出 "{:key@other :stuff}", 而 read-string 无法正确解释它。要么 pr-str 需要转义 @ 符号,要么 read-string 需要正确处理关键词内的符号。

背景:我在 Storm bolts 中传递一个映射,该映射将电子邮件地址作为键,这些 bolts 需要thrift-serializable形式。使用 pr-str/read-string 组合在这些键上失败,因此我退回到 JSON 序列化。

8 答案

0

由 stu 发布的评论

'@' 字符不是关键字或符号的合法字符(见https://clojure.org/reader)。已重新分类为增强请求。

0

由 stevenruppert 发布的评论

那么为什么 (keyword "keywith@") 不抛出异常呢?这似乎与您的声明不一致。

0

由 jafingerhut 发布的评论

Clojure 有一个长期特性,那就是它不会为非法的一切抛出异常。

0

由 stevenruppert 发布的评论

是的,但是read-string明确地处理了。函数“keyword” 不能 抛出异常,有很好的理由吗?考虑到符号名称内部的命名空间有其他特殊规则,"keyword"函数确实应该进行验证。

另一个解决方案可以是允许类似ruby的:"不允许字符的符号"文字,但这也可能与命名空间的处理方式混淆。

https://groups.google.com/forum/?fromgroups=#!topic/clojure/Ct5v9w0yNAE 关于这个话题有一些较老的讨论。

0

由 jafingerhut 发布的评论

免责申明:我不是Clojure/core成员,只是一个对此感兴趣的贡献者,并不了解此处所做的所有设计决策。

Steven,我觉得可能有两个问题:(1)执行这样的检查会比不执行检查要慢,并且(2)实现这样的检查意味着在合法符号、关键字、命名空间名称等规则变化时必须更新它们。

你对为贡献库添加严格版本的symbol和keyword函数,以及尝试测试大量规则边界情况(合法和非法)的测试套件感兴趣吗?我将这些问题视为严肃的问题,而不是修辞问题。这允许人们愿意使用这些函数的严格版本,同时也很容易测量严格和宽松版本之间的性能差异。

0

由 stevenruppert 发布的评论

回顾这个问题,问题的根本原因是{pr}函数,尽管它默认以“print(link: s)对象可以被reader读取的方式”(link: 0)进行打印,但并不总是这样做。因此,最简单的“修复”方法是将它的docstring更改为警告并非所有关键字都可以被读取回来。

更深层次的问题是symbol没有可以表示所有实际可能关键字的reader形式(在这种情况下,那些包含“@”的)。将实际可能的关键字限制为匹配reader形式,即编写一个严格的“keyword” function,在我看来,这实际上是一个更差的总体解决方案。更好的解决方案可能是以某种方式扩展keyword reader form,以便它可以表示所有可能的关键字,这可能包括ruby的:"keyword"语法。此外,该解决方案可以避免必须将假设的严格keyword/symbol函数与reader操作同步,以及编写相应的测试用例等。

因此,这个bug的解决取决于我们愿意走多远。更改docstring将是最容易的,但扩展keyword形式将是我心目中最好的解决方案。

(链接:0): https://docs.clojure.org/clojure_core/clojure.core/pr

0

由 jafingerhut 发布的评论

我昨天偶然遇到了ticket CLJ-17。其讨论线程显示,之前已经出现了验证构造关键字和符号内容的话题。当时编写了一个补丁,修改了"symbol"和"keyword"函数,以便符号/关键字像现在这样构造,但随后使用clojure.lang.RT/readString方法在字符串参数上进行了双重检查,以确保可读性。如果intern和readString方法返回的符号不相等(或者readString抛出异常),则会抛出异常。

Rich担心运行时开销会过高,并询问是否有人知道更好的方法。Chas Emerick提出使用类似Common Lisp的#|symbol with whitespace|语法来使所有符号可读,并对引用将会不必要的常见情况进行了一些检查。Rich对引用任意符号的想法持开放态度,但认为这将是不同的问题。

我不清楚自那以后是否有人创建一个议题来介绍任意符号的引用功能,但我可能错过了。这个议题可能导致那一个议题,但它的描述需要进行重大编辑,并在Clojure的多个地方需要代码更改。

0
参考资料:https://clojure.atlassian.net/browse/CLJ-1033(由alex+import报告)
...