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)实现此类检查意味着如果/当合法符号、关键词、名称空间名称等规则更改时,需要更新它们。

您是否愿意编写如symbol和keyword之类的函数的严格版本,并将其添加到贡献库中?并且编写测试套件以尝试触犯规则中的大量角向量,无论是合法的还是不合法的?我把它看作是严肃的问题,而不是修辞问题。这允许人们愿意使用这些函数的严格版本,同时也有助于衡量严格和宽松版本之间的性能差异。

0
答者:

评论者:stevenruppert

回顾这个问题,问题的根本原因是{pr}函数虽然默认“以link: s的形式打印对象,以便可以由读取器读取”,但并不总是这样做。因此,最简单的“修复”就是改变其docstring以警告并不是所有关键词都可以被读取。

更深层次的问题是symbol没有可以代表所有可能关键词的读取器形式(在这种情况下,有“@”在内的关键词)。将可能的关键词限制为与读取器形式相匹配,即编写一个严格的“keyword”函数,听起来像是更差的全局解决方案。较好的解决方案是某种方式扩展keyword读取器形式,使其能够表达所有可能的关键词,可能是ruby的“keyword”语法。此外,该解决方案还可以避免必须将与读取器操作同步的假设严格关键词/symbol函数,并为其编写测试用例等问题。

因此,这个错误修复的程度取决于我们愿意走多远。修改文档字符串是最容易的,但我认为扩展关键字形式将是最“好”的解决方案。

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

0

评论者:jafingerhut

我昨天偶然发现了问题跟踪号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 报告)
...