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

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

这就是为什么希望将该信息作为 fn 字段而不是 Var 的元数据存放的原因

0 投票

由:jafingerhut

Jozef,你是对的,参数向量上的非原始类型提示可能不是惯例。你能提供我可以阅读的资料吗?

0 投票

评论人:tsdh

只有带有参数向量提示的版本在 https://clojure.org/java_interop#Java 互操作类型提示中进行了文档说明。然而,在你只有一个参数(或所有参数返回同一类型值)的情况下,在 var 名称上也使用提示也有效。但两个版本似乎有不同的语义。请参阅 CLJ-1232。

0 投票
_评论人:wagjo_

类型提示是 Clojure 的一个复杂部分,但你几乎总是可以使用“*'place hint on a symbol'*”惯例。在参数向量上应用类型提示只有在以下两种情况下
- 原始提示
- 不同参数数量具有不同返回类的函数

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

第二种情况,即这里讨论的问题,仅在定义函数时使用。编译器首先在 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
用户 > (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 投票
by

由:wagjo

Andy,我发现了一些与我的建议相反的资料 :) 查看 CLJ-811 和(链接:1)。

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

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