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

欢迎!请参阅 关于 页面以了解更多信息。

0
打印

user=> (read-string (pr-str {(keyword "key@other") :stuff}))
RuntimeException 字典引用必须包含偶数个表单 clojure.lang.Util.runtimeException (Util.java:170)


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

背景:我正在通过 Storm 鞭子传递带有电子邮件地址的地图作为键,这些键需要 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”函数确实应该进行验证。

另一个解决方案是允许使用类似Ruby的"不允许字符的符号"字面值,但这可能会与命名空间的处理方式混淆。

https://groups.google.com/forum/?fromgroups=#!topic/clojure/Ct5v9w0yNAE 对这个主题的一些旧讨论。

0

评论由:jafingerhut

免责声明:我不是Clojure/core成员,只是一个感兴趣的贡献者,不了解这里所有的设计决策。

Steven,我认为可能有两个问题:(1)执行此类检查的速度可能比不执行它们时慢;(2)实施此类检查意味着如果/当合法符号、关键字、命名空间名称等的规则更改时,必须更新它们。

你是否有兴趣编写严格版本的函数如symbol和keyword,并添加到贡献库中?测试套件试图尝试规则中法律和非法的显著数量?我是认真的问题,不是修辞问题。这将允许希望使用这些函数的严格版本的人这样做,同时可以轻松地衡量严格和宽松版本之间的性能差异。

0

评论由:stevenruppert

回顾这个问题,问题的根本原因在于,{pr}函数虽然默认情况下以对象可以被reader读取的方式“print(link: s)”(link: 0),但不总是这样做。因此,最简单的“修复”方法就是更改其docstring以警告说不是所有关键字都可以被读取回来。

更深层次的问题是,symbol没有可以表示所有实际可能的关键字的reader形式(在这种情况下,包含“@”的符号)。将可能的实际关键字限制为与reader形式匹配,即实际上写入一个严格的“keyword”函数,似乎是一个更糟糕的解决方案。在我看来,更好的解决方案是扩展keyword reader形式以允许它表达所有可能的关键字,可能是Ruby的":keyword"语法。此外,该解决方案将避免需要将假设的严格keyword/symbol函数与reader操作保持同步,并为它编写测试用例,等等。

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

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

0

评论由:jafingerhut

我在昨天偶然发现了一份编号为CLJ-17的工单。其讨论线程显示之前已经出现过验证构造关键字和符号内容的问题。当时编写了一个补丁,修改了“symbol”和“keyword”函数,使得符号/关键字以当前的方式构建,但随后通过clojure.lang.RT/readString方法对字符串参数进行了双重检查,以确保可读性。如果内部和readString方法返回不同的符号(或者readString抛出异常),则会抛出异常。

Rich担心这种运行时开销过高,并询问是否有人知道更快的方法。Chas Emerick建议使用类似于Common Lisp的#|symbol with whitespace|语法,做一些针对引号不必要的一般情况的检查。Rich对引号任意符号的想法表示开放,但那将是另一个工单。

至今尚不清楚是否有人创建工单来引入引号任意符号,但可能遗漏了它。这个工单可能成为那个工单,但其描述需要重大编辑,Clojure的许多地方也需要代码更改。

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