2024年Clojure调查中分享你的想法!

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

+1
打印

函数的print-method实现旨在产生有效的edn语法吗?在某些情况下,它并不这样做

user> (require '[org.httpkit.server :as http])
user> (def s (http/run-server (fn [req] {:status 200}) {}))
user> (prn s)
#function[clojure.lang.AFunction/1]

符号名不能以数字开头,因此clojure.lang.AFunction/1在读取回时会导致解析错误

user> (clojure.edn/read-string (prn-str s))
Execution error at user/eval7394 (REPL:68).
Invalid token: clojure.lang.AFunction/1

这是预期的行为吗?如果是这样,打印并重新读取可能包含函数的数据结构可能会失败。

1 答案

0

选择
 
最佳回答

是的,这是预期的行为。函数不能以这种方式序列化,edn没有代表函数实例的表示。

我认为创建不可读标记文字的数字可能被认为是问题。
by
谢谢,Alex。这正是我好奇的不可读标记文字。处理标记文字是一个独立的话题;但我想print-method应该产生语法上有效的edn。
by
通常,print-method并不保证产生语法上有效的edn(有许多方式可以违反这个假设),甚至不能保证打印Clojure数据。是否支持edn打印或以更严格的方式实现print/read双向操作是在1.11版本中考虑工作的一个项目。
by
如果它在1.11版本中看到这将非常棒。如果有助于思考这项工作,以下是在我发布原始问题时的一个细节。

不可读的标记文字似乎不是由clojure自身生成的。cider-nrepl为某些对象类型添加了print-method实现,包括clojure.lang.AFunction。这通常是有帮助的;但多重方法的全局特性意味着这可能会让你吃惊(或者至少让你困惑)。当我在这个vanilla repl中测试这个时,看到pr-str产生不同的结果让我很惊讶。一种一致的打印数据结构的方式(不受环境的影响)并且由edn读取器保证可读的,确实是一个有用的功能。
by
啊,对了,我没有意识到这是cider添加的print函数。

整个打印基础设施被设计为可供用户修改,所以我认为使其独立于环境不是目标。
by
当然——用户可修改的是关键。但明确的范围有助于最小惊奇原则。

例如,edn/read的opts参数清晰地定义了用户自定义的行为,并使其推理变得简单。相比之下,在print-method中,我没有修改默认行为,但是Someone else全局地做了——有很好的理由。但它很令人惊讶,找回它的过程也很复杂。
...