2024 Clojure状态调查中分享您的想法!

欢迎!请查看关于页面以获取更多关于此工具的信息。

+1
语法和读取器

edn/read:readers参数接受一个标签符号到数据读取函数的映射,但*data-readers*需要一个标签符号到数据读取Vars(全局绑定)的映射。我只是在 wondering 是否存在什么原因导致了这种差异,因为不能在*data-readers*中使用匿名函数确实是一件让人头疼的事情。

背景是我制作了一系列相关的读取器标签(用于标记字面量),它们都大致相同。所以我不是创建了5个几乎相同的功能,而是创建了一个具有两个参数(标签,值)的功能。然后,我创建了一个reader-for函数,在需要时返回一个单一参数函数(使用partial和双参数函数)。这对于edn/read来说工作得很顺利,但当我去使用它在*data-readers*中时,它就是一个失败的尝试,因为没有reader-for输出的Vars。

有几个解决方案。例如,将*default-data-reader-fn*绑定并创建一个将转到所有读取器的函数。这并不特别困难,但现在我仍然有两个实体,而不是一个——为edn/read提供的读取器映射和为*default-data-reader-fn*提供的函数。当然,可以在函数中使用映射。或者,作为替代方案,我可以简单地编写5个函数,或者用“编写”doseq。但这些标签-executes 之间的细微差异确实有些令人费解。例如,除了{tag-sym fn}:reader映射和{tag-sym Var}*data-readers*映射之外,还有data_readers.clj中的{unquoted-tag-sym-in-a-map-literal fn-sym}语法,尽管它是clj文件,但似乎并不提供定义读取器的动态机会,只提供字面量映射。

也许我根本不了解这背后的实践、历史和逻辑,如果有人能阐明一些光线,我将不胜感激,如果不行,那也很好。

1 答案

+2
by
selected by
 
最佳答案

我在这个开发时不在核心小组中,所以我只能猜测,但我猜*data-readers*是有意与data_readers.clj的结构相关联的。

对于data_readers.clj,其意图是在代码中连接一个tag到必须加载的reader函数。这个文件是.clj而不是.edn,因为数据读取器是在Clojure 1.4中添加的,而edn规范尚未编写(那是在同年稍后发布的)。

许多有经验的Clojurists可能遇到的一个长期问题是,在edn中,没有一种标准方式来表示可调用的代码引用(如var)的引用。你最多只能发送符号,在需要时进行解析以恢复Var。在过去的几个版本中,我们逐步找到了这个问题的解决方案 - Var序列化(在Java中)在反序列化时重新连接到本地实现,添加了require-resolve并有助于符号方面。下一步可能是在edn中使vars可序列化(#var my/fn),然后创建一个内置的数据读取器来将它们反序列化为解析后的Var。如果所有这些都有,可能就是data_readers.edn了,其值为用var标记的literals而不是符号。

我想我的真正问题是,你是否能进一步挖掘 - 在何时需要修改*data-readers*的背后是什么原因?你在何种情况下不能直接向reader中注入你想要的数据读取器映射表?

by
谢谢,亚历克斯,我真的很感激你对历史这里进行的详尽说明,它使事物变得更加有意义。为了回答你关于我为什么在捣鼓 *data-readers* 的问题,我认为我当时并不理解 data_readers.clj 做了我需要做的所有事情。例如,当时对我来说并不清楚这个文件可以与库一起分发并且能够正常工作(我以为这只是个人用户制作的)。我还不知道它在 REPL 中也可以正常工作,可能是因为我花了一点时间来正确地使用语法,在此期间它没有在 REPL 中加载。(我的标记,例如命名空间,曾经被误命名为 "foo.bar.baz",而不是像符号一样 "foo.bar/baz",尽管我记不清这是不是 data_readers.clj 的问题,或者是 *data-readers* 的问题。它与 edn/read 一起以那种方式命名标签时可以正常工作,因此我花了点时间意识到我到底做错了什么。)

不管怎样,结果是我不需要捣鼓 *data-readers*。再次感谢你深思熟虑的回复。
...