请在 2024 Clojure调查问卷! 中分享您的想法。

欢迎!请参阅 关于页面 获取更多关于如何工作的信息。

+1
ClojureScript
考虑无参数的函数


(defn aarg {:arglists '([fake])} [])
=> {:ns cljs.user,
 :name aarg,
 :file nil,
 :end-column 11,
 :column 1,
 :line 1,
 :end-line 1,
 :arglists ([fake]),
 :doc nil,
 :test nil}


一切如预期进行,但当引入可变参数


(defn aarg {:arglists '([fake])} [& env])
(meta #'aarg)
=> {:ns cljs.user,
 :name aarg,
 :file nil,
 :end-column 11,
 :top-fn {:variadic true,
          :max-fixed-arity 0,
          :method-params [(env)],
          :arglists ([& env]),
          :arglists-meta (nil)},
 :column 1,
 :line 1,
 :end-line 1,
 :arglists ([& env]),
 :doc nil,
 :test nil}


:arglists 没有受到影响。

8 答案

0

评论者:hlolli

我刚刚提交了一个补丁,以前从未使用过 jira 补丁系统,除此之外,该补丁将使编译器尊重用户提供的 :arglists 元数据。希望能得到反馈和合并 :)

0

评论者:dnolen

谢谢你,你提交了 Clojure CA 吗?

0
已回答

评论者:dnolen

补丁审查,我不太理解改变可变参数函数的arity(可变参数数量)并添加这个新标志的目的。为什么不直接将这个逻辑放入可变参数函数中?

0
已回答
_hlolli 的评论:

是的,我会找到更好的解决方案来修复我的补丁,但这3176行的`m`符号问题我来解决。

m (conj {:arglists (core/list 'quote (sigs fdecl))} m)

合并了arglists,并且从这一点以后,就无法知道:arglists是否是从提供的元数据中来的。但是我会重命名let符号,很容易避免添加arity,我将在今天稍后再做另一个补丁。

我还没有提交Clojure贡献者协议,我现在正在填写...
0
已回答
_hlolli 的评论:

昨天我签署了Clojure CA
"Rich Hickey 和 Hlöðver Sigurðsson 之间的Clojure CA已签署并存档!"

代码
用于元数据的符号名m(m代表 metadata)已经不太好,但我只是添加了一个逗号来区分可变参数函数与其他情况。

我在测试中发现,多arity-fn的arglist元数据在与添加arglists与否都不兼容。如果是这样,我可以为这个问题打开另一个jira工单。
0
已回答
参考: https://clojure.atlassian.net/browse/CLJS-2351(由 hlolli 报告)
0

这同样适用于多arity函数。

(defn bar {:arglists '([foo bar])}
  ([x] 1)
  ([x y] 2))

(meta #'bar)
;;=> {:ns cljs.user,
 :name bar,
 :file nil,
 :end-column 10,
 :top-fn
 {:variadic? false,
  :fixed-arity 2,
  :max-fixed-arity 2,
  :method-params ([x] [x y]),
  :arglists ([x] [x y]),
  :arglists-meta (nil nil)},
 :column 1,
 :line 1, 
 :end-line 1, 
 :arglists ([x] [x y]), 
 :doc nil, 
 :test nil}

而单arity函数工作正常

(defn foo {:arglists '([foo])} [x] 1)
(meta #'foo)
;; => {:ns cljs.user,
 :name foo,
 :file nil,
 :end-column 10,
 :column 1,
 :line 1, 
 :end-line 1, 
 :arglists ([foo]), 
 :doc nil, 
 :test nil}

我认为可以通过检查在multi-arity-fnvariadic-arity-fn定义中元数据中是否已经存在一个:arglists键来解决这个问题。

我很愿意看到这个问题得到解决,如果你需要针对multi-arity-fn的修复补丁,请告知。

0

这张工单缺少对为什么需要此更改或它有用原因的解释?

修改 :arglists 直接会影响编译器生成的代码。如果元数据与实际函数定义不精确匹配,则会破坏可变参数调用甚至“丢弃”某些参数个数的调用。

我注意到,在 Clojure 和 ClojureScript 中,`eduction` 的定义覆盖了其 :arglists 元数据。
在 Clojure 中,至少,提供 :arglists 元数据以给编辑器和 REPL 提供有用的提示是一种相当常见做法。:arglists 元数据根本不影响语义,它只是提供便于阅读的提示。

以下在 Clojure 中是有效的:

dev=> (defn foo {:arglists ['(foo bar)]} ([x]) ([x y]))

#'dev/foo

dev=> (meta #'foo)

{:arglists ([foo bar]), :line 1, :column 1, :file "/home/seanc/.clojure/dev.clj", :name foo, :ns #object[clojure.lang.Namespace 0x34e700f4 "dev"]}
正如我所说的,有几个地方可能导致 `:arglists` 元数据影响生成的代码(例如 [CLJS-1871](https://clojure.atlassian.net/browse/CLJS-1871)。

针对文档用途,这样使用应该是可以的,但从工单描述中并不清楚。
在我这个例子中,纯粹是出于文档的目的,虽然我对CLJS代码库不太熟悉,但提出的补丁让我有点顾虑。与其覆盖内部的`arglists`变量,我宁愿在组合元数据时覆盖它,这样就不会产生后续影响。
在我这个例子中,纯粹是出于文档的目的。这一点很重要,否则编辑器的提示会显示gensyms而不是正确的名称。

 我对CLJS代码库不太熟悉,但提出的补丁让我有点顾虑。与其覆盖内部的`arglists`变量,我怀疑只在组合元数据时覆盖它是否会有助于解决这个问题,这样就不会产生后续影响。

```
meta     (assoc meta
                               :top-fn
                               {:variadic? variadic?
                                :fixed-arity mfa
                                :max-fixed-arity mfa
                                :method-params (core/cond-> sigs macro? elide-implicit-macro-args)
                                ;; FIX: something like this
                                :arglists (or (:arglists meta)
                                                          (core/cond-> arglists macro? elide-implicit-macro-args))
                                :arglists-meta (if (:arglists meta)
                                                 (doall (map meta (:arglists meta)))
                                                 (doall (map meta arglists)))})
```
...