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

欢迎!有关如何使用本站的信息,请参阅关于页面。

0
命名空间和变量
编辑

我正在使用pr-str序列化可能具有自动命名空间关键字的数据结构。

我想要在序列化之前减少数据结构不包含自动关键字,但不知道如何检测它?

(def x ::outbound)

(pr-str x) => "::outbound"

(edn/read-string "::outbound") => exception

(namespace x) => "current-namespace" 

那么,是否有办法知道x是否具有自动命名空间?

谢谢!

抱歉 - 没有在repl上运行就写下这个问题 - 下面是一个合适的例子。

(keyword ":out") => ::out

(pr-str (keyword ":out")) => "::out"

(edn/read-string (pr-str (keyword ":out"))) =>

Execution error at user/eval93457 (form-init751239350220000799.clj:1).
Invalid token: ::out

2 个回答

+2

自动解析命名空间不是关键字的属性。关键字只有一个命名空间和一个名称。自动解析的(::)关键字在读取时解析为带有命名空间的完全限定关键字。Clojure打印器永远不会打印包含::的关键字。

如果您想自定义打印机或使用其他功能来检测关键字命名空间与当前命名空间相同并将其打印为自动解析关键字,这是可能的(但几乎肯定不是一个好主意)。

edn/read-string不会读取自动解析关键字,因为edn规范不包括自动解析关键字。

谢谢,我也是这么想的,但不知道为什么我能够复现这个问题,我会进一步调查并找到原因后再提问。

谢谢

Timo
+1

编辑

在读取时,自动命名空间的关键词会被展开为普通命名空间的关键词,所以一旦你在数据结构中有了它们,就会带有命名空间打印出来。

$ clj
Clojure 1.10.0
user=> (pr-str ::out)
":user/out"

你是怎么让(pr-str ::out)打印出::out的?

编辑
你所观察到的就是clojure允许你构建在打印时不可读的关键词。
使用(keyword ":out")构建一个没有命名空间,名称为":out"的关键词,所以当它被打印成"::out"时,并不是说它被打印成“自动命名空间”,它只是按照识别为关键词的冒号":"打印其名称(":out")。你可以自由地从字符串构建关键词。
(keyword "heh [{:a 1}]" "//::! :: ::")将生成一个命名空间为"heh [{:a 1}]"、名称为"//::! :: ::"的关键词,其打印格式为:heh [{:a 1}]///::! :: ::

由于在你的情况下无法清理你的数据,我建议使用允许对不同类型进行自定义读取器和编写器的序列化,而不仅仅是edn。例如,可以查看transit


编辑
(keyword ":out") => ::out

(pr-str (keyword ":out")) => "::out"

(edn/read-string (pr-str (keyword ":out"))) =>

在用户/eval93457 (form-init751239350220000799.clj:1) 出现执行错误。
无效令牌: ::out

在我们的情况下,输入是动态的——我们目前的问题是它存储在Datomic历史记录中,无法删除——因此我们需要找到某种方法来修复序列化或反序列化。

clojure.core/read-string 会评估字符串并正确解析关键字,但它会打开安全问题,因此不应使用
by
哦,原来是这样的。你所观察到的 clojure 允许你构造一些在打印时不具可读性的关键字。
`(keyword ":out")` 构造了一个没有命名空间、名称为 `:out` 的关键字,所以在打印为 `"::out"` 时,它并不是打印为 `"autonamespaced"`,它只是将名称 (":out") 打印在冒号 ":" 后,从而标识它为关键字。你可以从字符串构造任意关键字
`(keyword "heh [{:a 1}]" "//::! :: ::")` 将产生一个有命名空间 `"heh [{:a 1}]"` 和名称 `"//::! :: ::"` 的关键字,它被打印为 `:heh [{:a 1}]///::! :: ::`。

由于在你的情况下无法清理数据,我建议使用允许为不同类型提供自定义读取器和写入器的序列化方法,而不是 edn。例如,可以查看 [transit](https://github.com/cognitect/transit-clj)
...