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

欢迎!请查看关于页面以获取更多关于工作方式的详细信息。

0
编译器

我原本期望以下两个 Java 交互调用都会避免反射,但只有第一个涉及 f1 的。

`
Clojure 1.6.0
user=> (set! warn-on-reflection true)
true
user=> (defn f1 ^java.util.LinkedList [coll] (java.util.LinkedList. coll))

'user/f1

user=> (def f2 (fn ^java.util.LinkedList [coll] (java.util.LinkedList. coll)))

'user/f2

user=> (.size (f1 [2 3 4]))
3
user=> (.size (f2 [2 3 4]))
反射警告,NO_SOURCE_PATH:5:1 - 无法解析对 size 字段的引用。
3
`

不确定这与 CLJ-1232 有何关系,但它是测试该问题的变体时发现的。

8 答案

0

评论者:jafingerhut

这是一个很棒的报告编号,1543。哥白尼最著名的书籍出版的年份:http://en.wikipedia.org/wiki/Nicolaus_Copernicus

0

评论者:wagjo

arg 向量的类型提示不应该是仅针对基本类型提示吗?据我所知,非基本类型提示应该位于函数名上,其他所有都是非惯用的。

0

评论者:bronsa

这不是参数向量提示与函数名提示之间的问题。
问题在于,不能在匿名函数上放置返回类型提示,而只能放在defn定义上,因为:arglists将作为Var元数据的一部分由defn添加。

这就是为什么我喜欢把信息作为一个函数上的字段而不是作为一个Var元数据上的元数据的原因之一。

0

评论者:jafingerhut

Jozef,您可能说得对,参数向量上的非原始类型提示是非习惯的。您是否有我能阅读的相关资料来源?

0

评论者:tsdh

只有带有参数向量提示的版本在https://clojure.org/java_interop#Java Interop-Type Hints上有文档说明。然而,在您只有一个参数(或者所有参数返回相同类型的值)的情况下,在var名称上的提示也是有效的。但两种版本似乎具有不同的语义。请查看CLJ-1232。

0
_评论者:wagjo_

类型提示是Clojure中非常复杂的一部分,但你几乎总是可以应用 一个符号的“放置提示”的技巧。在arg向量上对类型提示的生成,必须是以下两种情况之一
- 原始提示
- 不同参数的返回类型不同

第一种情况下,在编译fn*(见[1])时需要类型提示,不是之后,因此你必须在arg向量上指定它们。

第二种情况,即此处讨论的问题,必须在定义时使用defn。编译器首先查找var元数据中的标签,如果没有找到,则有一个特殊情况,在其中它查找带有不同参数的返回类型的情况的:arglist元数据。这显然是一个非常特殊的情况 [2],以处理具有不同参数的不同返回类型的情况。显然,使用def而不是defn不会为您创建一个:arglist元数据,因此您会看到反射警告。示例


user=> (def f2 (fn ^java.util.LinkedList [coll] (java.util.LinkedList. coll)))
#'user/f2
user=> (.size (f2 [2 3 4]))
反射警告,/tmp/form-init.clj:1:1 - 无法解析字段size的引用。
3
user=> (alter-meta! #'f2 assoc :arglists '(^java.util.LinkedList [coll]))
{:ns #<Namespace user>, :name f2, :file "/tmp/form-init.clj", :column 1, :line 1, :arglists ([coll])}
user=> (.size (f2 [2 3 4]))
3


顺便说一下,CLJ-1491有一个与这个话题略有相关的讨论。

[1] https://github.com/clojure/clojure/blob/03cd9d159a2c49a21d464102bb6d6061488b4ea2/src/jvm/clojure/lang/Compiler.java#L5134
[2] https://github.com/clojure/clojure/blob/03cd9d159a2c49a21d464102bb6d6061488b4ea2/src/jvm/clojure/lang/Compiler.java#L3572

0

评论者:wagjo

Andy,我找到了一些反对我的推荐的意见 :) 看CLJ-811和(链接:1)。

(链接:1) https://groups.google.com/d/msg/clojure/b005zQCPxOQ/6G0AlWKKKa0J

0
参考: https://clojure.atlassian.net/browse/CLJ-1543(由jafingerhut报告)
...