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没有表示函数实例的方式。

我猜创建不可读带标签字面值的数字可能被认为是一个问题。
谢谢你,Alex。这正是我好奇的不可读带标签字面值。处理带标签字面值是一个独立的话题;但我认为print-method应该产生符合语法的edn。
一般来说,print-method并不保证产生符合语法的edn(有很多方式违反这个假设),甚至不能保证打印Clojure数据。是否支持edn打印或以一种更强的方式支持print/read roundtrip,这是在1.11版本工作中的一个考虑项。
在1.11版本中看到这一点将会非常出色。假设这有助于思考该项工作,以下是在我提出原始问题时没有注意到的细节

不可读的带标签字面值似乎不是由Clojure自身生成的。cider-nrepl为特定对象类型添加了print-method实现,包括clojure.lang.AFunction。这通常是很有帮助的;但由于多方法的全球性质,这可能会造成麻烦(至少会让你感到困惑)。我在普通的repl中测试pr-str时,看到它产生了不同的结果,这让我感到很惊讶。一种能够保证一致(不受环境影响)并且可读(通过edn读取器)的打印数据结构的方法将是一个非常有用的特性。
啊,对,我没有意识到这是cider添加的打印函数。

整个打印基础设施设计成可以由用户修改,所以我认为将其与环境独立不是目标。
当然 —— 用户可配置是关键。但显式范围有助于最小惊讶原理。

例如,edn/read的opts参数使得用户定义的行为清晰且易于推理。相比之下,在使用print-method时,我没有修改默认行为,但是其他东西——全局的——做了修改。这有一个很好的理由。但它令人惊讶,并且追踪起来并不简单。
...