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

欢迎!请参阅 关于 页面以获取更多有关如何使用此工具的信息。

0
Clojure
h1. 理由

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


user> ::foo/bar
RuntimeException 无效的标记:::foo/bar  clojure.lang.Util.runtimeException (Util.java:221)


然而,对于符号,不存在此类语法。这是函数如 {{clojure.spec.test.alpha/instrument}} 出现错误的一个常见来源,该函数接受变量名称的限定符号作为参数。目前,此类符号字面量的首选表示法是语法引号,它当然接受任何命名空间。现在,如果在一个诸如 symbolic arguments 之一的符号 arguments 中意外地引用了一个当前命名空间中没有声明的别名(例如,当将一些代码从一个命名空间移植到另一个命名空间时),将非常有用,有与自动解析关键字相同的错误行为。以 {{instrument}} 为例,最终会调用昂贵的实际函数而不是模拟函数,而这些模拟函数可能会很容易地被忽略。

h1. 建议的语法

这有些棘手。最先想到的是双反引号,例如 {{``foo/bar}},但这已经有意义了,并且在现有的宏中可能会被使用。我猜测 {{%foo/bar}} 可能可行,尽管当然不能保证这不会在实际命名空间名称中使用。

h1. 状态

正如您所知,我尚未对可能的语法选项进行广泛调查,也没有开始编写补丁。只是想征求对此问题的意见,看看是否值得进一步追求。

4 答案

0
_由:alexmiller_ 评论

虽然我理解您的用例,但这将是语法上的重大添加,我认为这不太可能。我现在会将此添加到待办事项中。
0
_评论者:dergutemoritz_

同意,这是一个相当侵入性的变更,可能不值得麻烦。顺便说一句,在此期间,我想通过加标签的文本来实现同样的功能。如果有人正在寻找解决方案,你可以有一个这样的函数


(defn 自动解析符号读取器 [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/自动解析符号读取器}


现在您可以用它来完成与 {{::foo/bar}} 相似的效果,对这样的关键词


'#sym foo/bar
0
_评论者:dergutemoritz_

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


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


当然,现在您需要取消引用值。请注意,语法引用必须应用于整个表达式 - 如果它在键的前面,由于它已经被语法引用命名空间化,映射的命名空间将不会应用于它。实际上,人们可以预期 ::foo{'bar some-fn} 也会命名空间符号键,但这并没有发生。也许它只是在语法引用之后意外地这样工作的...
0
参考:https://clojure.atlassian.net/browse/CLJ-2490(由 alex+import 报告)
...