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

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

0
Clojure
h1. 理由

当自动解析的关键字字面量的命名空间部分引用了一个未声明的别名时,读取器会产生一个错误,如下所示


user> ::foo/bar
RuntimeException 无效令牌:::foo/bar  clojure.lang.Util.runtimeException (Util.java:221)


然而,对于符号来说,不存在这样的语法。这是诸如 {{clojure.spec.test.alpha/instrument}} 等函数中常见错误的原因,这些函数接受以 var 名为参数的限定符号。目前,此类符号字面量的首选表示法是语法引号,它当然接受任何命名空间。现在,当一个人不小心参考了象征性参数中的一个别名(这些别名在当前命名空间中尚未声明,例如当从一个命名空间移植代码到另一个命名空间时),那么具有与自动解析关键字相同的错误行为会非常有用。以 {{instrument}} 示例来说,人们最终可能会调用昂贵的真实函数而不仅仅是模拟,这可能是很容易忽视的。

h1. 建议的语法

这有点棘手。首先想到的是双反引号,如 {{``foo/bar}},但这已经有意义,并且很可能会在现有的宏中已使用。我想 {{%foo/bar}} 可能会起作用,尽管无疑没有保证它没有在实际的命名空间名称中使用。

h1. 状态

如您所见,我还没有对可能性的语法选项进行全面调查,而且我也还没有开始修改补丁。我只是想就这个问题征求意见,看看是否值得进一步 pursuing 解决这个问题。

4 个答案

0
_Comment made by: alexmiller_

虽然我理解您的用例,但这将是太大的语法补充,我认为这不太可能。我将暂时将其归入待办事项清单。
0
评论者:dergutemoritz

我同意,这无疑是一个相当侵入性的变更,可能不值得烦恼。在此期间,我想同样可以通过带标签的字面量实现同样的效果。对于寻找解决方案的人来说,你可以有一个这样的函数:


(defn auto-resolved-symbol-reader [sym]
  (let [ns (if-let [alias (namespace sym)]
          (or (get (ns-aliases *ns*) (symbol alias))
                 (throw (ex-info (str "符号 " sym " 的命名空间别名无效")
                                 {:symbol sym})))
             *ns*)]
    (symbol (name (ns-name ns)) (name sym))))


例如,将其注册为 {{sym}} 标签,只需将其放入类路径根目录下的 {{data_readers.clj}}


{sym my.data-readers/auto-resolved-symbol-reader}


现在你可以使用它来实现与 {{::foo/bar}} 同样的效果,对于这样的关键词:


'#sym foo/bar
0
评论者:dergutemoritz

例如,对于 {{instrument}} 示例中的 {{:replace}} 参数,还有一个已经工作的解决方案。只需按如下方式使用带有语法引号的自动解决映射命名空间:


:replace `::foo{bar ~some-fn}


当然,现在你需要将值解除引用。请注意,语法引号必须应用于整个表达式——如果它位于键之前,由于语法引号已经为其命名了空间,因此映射的命名空间将不会应用。
0
参考:[CLJ-2490](https://clojure.atlassian.net/browse/CLJ-2490) (由 alex+import 报告)
...