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

欢迎!请参阅关于页面以了解此工作的更多信息。

0投票
Clojure

Vars,虽然是一种通用的引用结构,但用于实现绑定,并且具有反映这一现实的特殊读取器和打印符号。与共享Vars的"name/namespace"记法的Keywords和Symbols不同,Vars没有实现clojure.lang.Named接口,即使它们打印时会像命名的一样。

附带的补丁实现了Vars上的Named。

示例

`
user=> (name :clojure.core/conj)
"conj"
user=> (namespace :clojure.core/conj)
"clojure.core"
user=> (name 'clojure.core/conj)
"conj"
user=> (namespace 'clojure.core/conj)
"clojure.core"
user=> (name #'clojure.core/conj)
"conj"
user=> (namespace #'clojure.core/conj)
"clojure.core"
user=> (with-local-vars [x 1] (name x))
"--unnamed--"
user=> (with-local-vars [x 1] (namespace x))
nil
user=> (with-local-vars [x 1] (println x))

<Var: --unnamed-->

`

这对于像CinC项目这样的应用来说很有用,其中Vars经常直接作为值使用,在这种情况下,它们理想上可以与它们所代表的表达式的绑定值交换。

7 个答案

0投票

评论者:bronsa

使用此补丁在未命名的Var上调用的{name方法将导致NPE,我认为这不是期望的行为。

0投票

评论者:arrdem

我同意,然而这种行为在Core中看起来是标准的。

Clojure 1.6.0
user=> (name nil)
NullPointerException clojure.core/name (core.clj:1518)
user=> (namespace nil)
NullPointerException clojure.core/namespace (core.clj:1526)

我还不能确信未绑定的{name}或{namespace}有意义的,在这种情况下,NPE可能是可接受的。

0投票

评论者:bronsa

我说的不是未绑定变量,而是匿名变量,我认为你可能写错了。

我同意你的观点,抛出异常可能是一种合理的行为,除非我在调用它的name之前对它进行nil测试,因为目前还没有方法可以测试一个变量是否已命名,除非尝试直接访问.name字段,这正是这个工单的目的。

0投票

评论者:bronsa

我和Reid在IRC上讨论了这个问题,以下是一些讨论结果
变量可以是未命名的(例如by with-local-vars返回的变量)或者同时包含命名空间和名称部分(这是interned变量的情况)
目前没有方法可以测试变量的"internedness",因此访问变量的.name或.Namespace字段来测试nil是当前唯一的方法

鉴于上述情况,当前的补丁似乎不太令人满意,以下是一些提出的解决方案
使变量成为命名变量,对于未命名的变量,让命名空间返回nil,让名称返回"--unnamed--"
保持变量不实现Named,添加一个"var-symbol"函数,返回变量ns+name对应的命名空间符号,对于未命名的变量返回nil

我个人更倾向于实现第二个解决方案,因为我认为在变量可以未命名且这在我看来似乎有些矛盾的情况下,变量不应该被命名为Named。

0投票

评论者:arrdem

明确处理未命名变量情况的补丁已被添加。

0投票

评论者:arrdem

将所有补丁压缩为一个diff文件,并更新了附件。

0投票
...