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

欢迎!请查阅 关于 页面了解更多此网站信息。

0
Clojure

变量,虽然是一种通用的引用结构,但用于实现绑定,并且具有反映这一现实特色的特殊读取器和打印表示法。与关键字和符号不同,它们与变量的 "namespace/name" 表示法共享,变量在打印时看似实现了命名,但实际上并没有实现 clojure.lang.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 项目这样的应用程序很有用,其中变量通常直接用作值,在这种情况下,它们最好可以与表示它们的值的符号互换。

7 答案

0

评论者:bronsa

使用此补丁执行未命名变量的 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)

我也并不认为未绑定变量的“名称”或“命名空间”有何意义,在这种情况下,非空指针例外(NPE)可能是可以接受的。

0

评论者:bronsa

我讨论的不是未绑定变量,而是匿名变量,我想你可能弄错了。

我同意你的观点,抛出异常可能是一种合理的操作,但我可以在调用 name 方法之前检测 nil,而检测一个变量是否已命名则没有方法,除非直接访问 .name 字段,而这正是本票据解决的问题。

0

评论者:bronsa

我和 Reid 在 IRC 上讨论了这个问题,以下是一些讨论结果
变量可以是未命名的(with-local-vars 返回的变量都是这样的),或者包含命名空间部分和名称部分(这对于 interned 变量而言是这种情况)
目前没有方法检测变量是否为 interned,因此,访问变量的 .name 或 .namespace 字段来检测 nil 是唯一的方法

鉴于上述情况,目前的补丁似乎不太令人满意,以下是一些解决方案
让 Var 命名,对未命名的 Var,让命名空间返回 nil,名称返回 "--unnamed--"
保持 Var 不实现 Named,添加一个 "var-symbol" 函数,返回与 Var 的 ns+name 匹配的命名空间符号,或对于未命名的 Var 返回 nil

就我个人而言,我更希望第二个方案被实施,因为我认为 Var 不应该被命名为 Named,因为它们可以是未命名的,而这在我看来似乎是一种矛盾

0

评论者:arrdem

为未命名的变量明确添加了补丁。

0

评论者:arrdem

将所有补丁合并为一个 diff 并更新了附件。

0
参考:https://clojure.atlassian.net/browse/CLJ-1488(由 arrdem 报告)
...