Clojure 2024 年调查 中分享您的观点!

欢迎!请参阅 关于 页面以获取更多关于该操作的信息。

+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。这正是我好奇的那些无法读取的标记字面量。处理标记字面量是一个单独的话题;但我认为打印方法应该能够生成有效的edn。
一般来说,print-method 并不保证生成合乎语法的edn(有许多方式会违反这一假设),甚至不能保证打印Clojure数据。是否支持edn打印或在1.11的更强方式中进行print/read往返,这些都是正在考虑中的工作内容。
如果能成为1.11中的一个亮点,那将非常棒。如果这有助于对该工作进行思考,以下是我最初提问时未曾注意到的细节。

无法读取的标记字面量似乎不是由Clojure本身生成的。cider-nrepl为某些对象类型添加了print-method实现,包括clojure.lang.AFunction。这通常是有帮助的;但是多重方法的全球性质意味着这可能会让您感到惊讶(或至少会让人困惑)。我在vanilla repl中测试时看到pr-str产生不同的结果让我很惊讶。打印数据结构的途径应该是连贯的(不受环境影响),并且保证可读取(由edn读取器保证)的功能无疑非常有用。
啊,明白了,我没有意识到这是cider添加的打印函数。

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

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