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

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

+40
命名空间和变量
已关闭

制作限定关键字非常有用,尤其是与spec一起使用时。使用命名空间别名有助于处理大量的限定关键字。然而,当前创建别名命名空间需要该命名空间实际上存在。

这项工单是一个占位符,用于对关键字轻量级别名做一些更深入的工作。详情待定。

关闭备注:Clojure 1.11.0-alpha2在`require`中新增了对`:as-alias`的支持。这就像`:as`一样创建别名,但不会触发加载。详见CLJ-2123获取详情。

9 个回答

0

评论者:bendlas

希望能在1.9beta发布之前就开启对这个问题的讨论。

在我之前的项目工单CLJ-2030中,理由是创建一个结构,允许在.cljc文件中进行自动别名,我将它作为一个需求提交。显然,在cljs中声明自动别名的最佳位置是ns子句。
如果我们不想为这种情况增加别名,我建议在ns子句中增加一个用于声明关键字别名的声明。让我们为这个评论提供一个工作标题:<(:kwns-alias ...)。

:kwns-alias将用于为::qualified/keywords创建命名空间别名。

一个开放式问题是,:kwns-alias 应该如何与别名交互。也就是说,::qualified/keyword 的命名空间是否应该始终扩展到与 qualified/symbol 相同的命名空间,或者是否应该允许它们不同。我认为它们应该始终相同,因为这符合简单性的规则。这意味着
- 别名需要检查 sym 是否已在 :kwns-alias 中,并在是的情况下抛出异常
- :kwns-alias 还需要处理 `qualified/keywords 的名称可能不再需要 knws

那么,:kwns-alias 的好名字是什么?:let 可能吗?

0

评论者:alexmiller

beta 功能完整,所以这个功能不会出现在 1.9 中。

我觉得向 ns 添加任何内容都可能不在议程上,但在我了解更多关于 Rich 的想法之前,我无法提出更多的建议。

0

评论者:bendlas

很遗憾,但也许 1.10 会缩短发布周期...

无论如何,我对 Rich 提出的在外部进行外部操作的同时还能与 clojurescript(甚至 clojure,毕竟是……)相适应的想法非常感兴趣。
你有什么理由认为增长 ns 对此是个糟糕的主意吗?

0

评论者:alexmiller

ns 已经做了很多事情,我们并没有任何意愿让它做更多的事情。

0

评论者:bendlas

由于 ns 对于 clojure 中命名空间的设置至关重要,我认为针对该问题(ns 执行操作过多)的解决方案意味着对现有技术的巨大改变。既然我们不能打破 ns,我想象着要么是某种 ns2,要么是在 ns 子句之外进行命名空间设置的方法。无论如何,我都很好奇。

由于我知道 Rich 不会被他的吊床时间困扰,我现在就先放下这个议题。我肯定会再次检查,当下一轮 alpha 版发布的时候。我也希望在这段时间内有一些富有成效的讨论。

0

评论者:tslocke

有什么理由这样一个机制要局限于关键字吗?在我的代码中,这样的特性对符号来说非常有用。

此外,相关:让 pr-str(以及其他类似工具)能够配置使用命名空间简短版本。即使是带有命名空间映射的调试输出也会非常嘈杂。

0

评论者:alexmiller

没有特别的原因——通常,对于此类问题,我们会为任何标识符(关键字或符号)使其工作方式相同。

0
参考:[链接](https://clojure.atlassian.net/browse/CLJ-2123)(由 alexmiller 报告)
0

我们用一对宏来解决这个办法。它们有点难看,但是有效——我们已经用了大约四个月,没有出现任何问题。我们的团队对 Clojure 还比较新,所以很想知道为什么这不是一个好主意...

(ns com.flexport.util.synthetic-ns
  "Synthetic namespaces are designed to be used as prefixes for namespace-qualified keywords.
  They allow us to decouple the names of data from the names of code.")

(defmacro def-synthetic-ns
  "Define a synthetic ns (the-ns), binding it to the-alias.

  Example:

  (def-synthetic-ns loan 'flexport.capital.loan)

  ::loan/name
  ;; flexport.capital.loan/name

  ::loan/id
  ;; flexport.capital.loan/id
  "

  [the-alias the-ns]
  `(do
     (def ~the-alias ~the-ns)
     (create-ns ~the-ns)
     (alias (quote ~the-alias) ~the-ns)))

(defmacro use-synthetic-ns
  "Use a synthetic ns alias defined elsewhere.

  Example:

  (ns ns-a
    (:require [com.flexport.util.synthetic-ns :refer [def-synthetic-ns]]))

  (def-synthetic-ns loan 'flexport.capital.loan)

  ::loan/a
  ;; flexport.capital.loan/a

  (ns ns-b
    (:require [com.flexport.capital.util.synthetic-ns :refer [use-synthetic-ns]])
    (:require [ns-a :as ns-a]))

  (use-synthetic-ns ns-a/loan loan)

  ::loan/b
  ;; flexport.capital.loan/b
  "

  [the-alias local-name]
  `(alias (quote ~local-name) (var-get #'~the-alias)))
...