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

欢迎!请参阅 关于 页面以了解有关其工作原理的更多信息。

0
打印

user=> (read-string (pr-str {(keyword "key@other") :stuff}))
RuntimeException Map literal must contain an even number of forms  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)实现此类检查意味着在法定符号、关键词、命名空间名称等的规则更改时需要更新它们。

您是否有兴趣编写symbo和keyword等函数的严格版本,并将它们添加到 contrib 库中?以及测试套件测试规则中的大量边缘情况,如合法项与非法项?这应当被视为严肃的问题,而非修辞问题。这允许想使用这些函数严格版本的程序员这样做,同时也可以轻松地比较严格版本和宽松版本之间的性能差异。

0

由 stevenruppert 发布的评论

回顾这个问题,问题的根本原因是{pr}函数虽然默认以某种方式"print(link: s)使得对象可由读取器读取",(link: 0),但它并不总是会这样做。因此,最简单的"修复"方法是更改其文档字符串以警告说,并不是所有关键词都可以被读取回。

更深的问题是没有reader形式可以表示所有实际可能的关键词(在这种情况下,包含"@"的关键词)。将实际可能的关键词限制为与reader形式相匹配,即编写一个严格的"keyword" 函数,在我看来整体上似乎是更差解决方案。更好的解决方案是扩展keyword读取器形式以使其能表示所有可能的关键词,这可能包括ruby的::"keyword"语法。此外,该解决方案将避免需要将假设的严格关键词/symbol函数与reader操作保持同步,并编写测试案例等。

因此,这个错误的解决方法取决于我们的决心。修改文档字符串可能最简单,但扩展关键字形式可能是我认为的“最佳”解决方案。

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

0
回答: by

由 jafingerhut 发布的评论

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

Rich 担心这种运行时开销太高,并询问是否有人知道更快的处理方式。Chas Emerick 建议使用类似于 Common Lisp 的 #|symbol with whitespace| 语法,并针对引号在常见情况下不必要的常见情况进行了检查。Rich 对引号任意符号的想法持开放态度,但它将是一个不同的票据。

我不知道此后是否有人创建一个票据来引入任意符号的引号,但我可能错过了。这个票据可能是那个票据,但是它的描述需要重大的编辑,并且 Clojure 的许多地方都需要代码更改。

0
回答: by
参考:https://clojure.atlassian.net/browse/CLJ-1033(由 alex+import 提出)
...