请在 2024 Clojure 状态调研! 中分享您的想法。

欢迎!有关本站点的工作方式,请参阅 关于 页面获取更多信息。

0 投票
Clojure

变量在作为一个通用的引用结构时,用于实现绑定,并且有反映这一现实的特殊读取器和打印符号。与共享“命名空间/名称”符号的 Keywords 和 Symbols 不同,变量在打印时虽然像命名一样,但实际上并没有实现 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之前,我可以测试它是空值,而没有办法测试变量是有名的还是有别名的,除非直接尝试访问.name字段,这正是这个工单要做的事情。

0 投票
提问者:

评论者:bronsa

我和Reid在IRC上讨论了这个问题,以下是一些讨论结果
变量可以是未命名的(如with-local-vars返回的变量)或同时包含命名空间和名字部分(这是interned变量的情况)
目前无法测试变量的“interned”状态,因此访问变量的.name或.namepaces字段是测试唯一的办法

基于以上讨论,当前的补丁似乎还不令人满意,以下是一些提出的解决方案
将变量改为命名变量,对于非命名变量,使命名空间返回nil,名字返回"--unnamed--"
保持变量不实现Named接口,增加一个"var-symbol"函数,返回命名空间符号和一个匹配变量ns+name的符号,对于非命名变量返回nil

我个人更倾向于第二种解决方案实现,因为我认为变量不应该是有名的,它们可以是未命名的,这在我看来是矛盾的。

0 投票
提问者:

评论者:arrdem

添加了专门处理未命名变量情况的补丁。

0 投票
提问者:

评论者:arrdem

将所有补丁合并到一个diff文件中,并更新了附件。

0 投票
提问者:
参考资料:https://clojure.atlassian.net/browse/CLJ-1488 (由arrdem报告)
...