在<_variables>2024_state_of_clojure调查!

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

0
Clojure
h1. 原因

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


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


然而,对于符号,没有这样的语法。这是函数(如{{clojure.spec.test.alpha/instrument}})的常见错误来源,这些函数接受具有变量名称的合格符号作为参数。目前,这种符号字面量的首选符号是语法引用,它当然接受任何命名空间。现在,如果某人不小心在那些符号参数中引用了在当前命名空间中未声明的别名(例如,将一些代码从一个命名空间移植到另一个命名空间),那么拥有与自动解析关键字相同的错误行为将会非常有用。以{{instrument}}为例,最终可能会调用潜在昂贵的真实函数而不是模拟,这很容易被忽视。

h1. 建议的语法

这有点棘手。首先想到的是双反引号,如在{{``foo/bar}}中,但这已经具有含义,并且可能会在现有的宏中被使用。我想{{%foo/bar}}可能可以工作,尽管当然不能保证这个名称 hasn't already been used in actual namespace names, too.

h1. 状态

正如你所见,我还没有对可能的语法选项进行详细的调查,也没有开始着手修复。我只是想征求对这个问题的意见,看看是否值得进一步追究。

4 答案

0
_由:alexmiller_发表的评论

虽然我理解你的用例,但这将会是一个大的语法变更,我认为这不太可能。我现在将其放入待办事项。
0


同意,这是一个相当侵入性的改动,可能不值得麻烦。不管怎样,在此期间,我想同样的效果可以通过一个带标签的字面量实现。如果有人正在寻找解决方案,你可以使用以下此类函数:


(defn auto-resolved-symbol-reader [sym]
  (let [ns (if-let [alias (namespace sym)]
             (or (get (ns-aliases *ns*) (symbol alias))
                 (throw (ex-info (str "Invalid namespace alias on symbol " 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


在 {{instrument}} 示例的 {{:replace}} 参数的情况下,还有一个已经奏效的解决方案。只需像这样使用带语法引号的自动解析地图命名空间


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


当然,现在你需要取消字面量。请注意,语法引号必须应用于整个表达式 - 如果它位于键之前,该映射的命名空间将不会应用于它,因为它已经被语法引号命名空间化。实际上,人们可能期望 ::foo{'bar some-fn} 也会命名空间符号键,但事实并非如此。可能它只是意外地在语法引号之后奏效...
0
参考:[https://clojure.atlassian.net/browse/CLJ-2490] (由 alex+import 报告)
...