gpt4 book ai didi

types - 用于 Longs 的 Clojure 重载方法解析

转载 作者:行者123 更新时间:2023-12-04 06:22:28 26 4
gpt4 key购买 nike

这种行为对我来说毫无意义:

user=> (type 1)
java.lang.Long
user=> (type (cast Long 1))
java.lang.Long
user=> (type 1)
java.lang.Long
user=> (type (Long. 1))
java.lang.Long
user=> (type (cast Long 1))
java.lang.Long
user=> (BigDecimal. 1)
1M
user=> (BigDecimal. (Long. 1))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: java.math.BigDecimal, compiling:(NO_SOURCE_PATH:22)
user=> (BigDecimal. (cast Long 1))
1M

为什么 (BigDecimal. (Long. 1)) case 未能找到明确的匹配方法签名,而其他两个表达式(具有完全相同的参数类型)成功?

更新:

我发现这种行为更奇怪的是它似乎是 Long 所特有的。类型:
user=> (BigDecimal. (Long. 1))
CompilerException java.lang.IllegalArgumentException: More than one matching method found: java.math.BigDecimal, compiling:(NO_SOURCE_PATH:1)
user=> (BigDecimal. (Integer. 1))
1M

最佳答案

来自 this discussion on the Clojure discussion group您似乎遇到了 Rich Hickey 做出的设计决策。具体来说,因为 BigDecimal 没有签名 BigDecimal(Long long) 的构造函数 (编辑:,因此编译器必须在 intlong 构造函数之间进行选择 - 请参阅下面的评论以讨论为什么使用 Integer 有效),编译器不会尝试“猜测”哪个构造函数你的意思是,并且明确地失败了。

The bottom line is specific type requirements on the Java side require explicit boxing on order to have correct and non-brittle code. - Rich Hickey



请注意,根据 this documentation,文字被解析为原语,而不是“盒装”类型。 :

In contrast to previous versions of Clojure, numeric literals are parsed as primitive longs or doubles.



要了解其他操作为何有效,您必须深入研究 Clojure 源代码,特别是 Compiler.java及其内部类 NumberExpr .这就是你的文字被自动装箱到 Long 的地方。并且编译器依次调用 Object.getClass()没有问题( typeclass 都这样做)。

Compiler.getMatchingParams() ,Clojure 编译器尝试解析 BigDecimal 的哪个构造函数使用。但是,您已明确指定参数的类型为 Long - BigDecimal 没有采用该类型的构造函数。

也许这不是“常识”,但 Rich Hickey 做出了这样的决定:您需要准确了解参数的类型,并且它们必须与 Java 类的类型相匹配。编译器拒绝猜测您的意图。

请注意以下事项:
user=> (new BigDecimal 1M)
Reflection warning, NO_SOURCE_PATH:33 - call to java.math.BigDecimal ctor can't be resolved.
IllegalArgumentException No matching ctor found for class java.math.BigDecimal clojure.lang.Reflector.invokeConstructor (Reflector.java:183)

另请注意,此 Java 代码有效并解析为 int BigDecimal 的构造函数:
    byte b = 1;
new BigDecimal(new Byte(b));

但是这段代码也失败了(即使它“应该”使用 int 构造函数):
user=> (BigDecimal. (Byte. (byte 1)))
Reflection warning, NO_SOURCE_PATH:37 - call to java.math.BigDecimal ctor can't be resolved.
IllegalArgumentException No matching ctor found for class java.math.BigDecimal clojure.lang.Reflector.invokeConstructor (Reflector.java:183)

tl;dr:Clojure 支持 Java 互操作,但这并不意味着它必须遵循 Java 语言规范的推广规则。

cast 呢? ?

下面的评论询问 (cast) .在这种情况下,您明确告诉 Clojure 编译器将类型解析委托(delegate)给 JVM。请注意以下(无意义的)代码编译,但在运行时失败:
user=> (set! *warn-on-reflection* true)
true
user=> (defn make-big-dec [obj] (BigDecimal. (cast Math obj)))
Reflection warning, NO_SOURCE_PATH:7 - call to java.math.BigDecimal ctor can't be resolved.
#'user/make-big-dec
user=> (make-big-dec 1)
ClassCastException java.lang.Class.cast (Class.java:2990)

结语二

在 Clojure 社区中,关于这个主题的讨论相当多。请查看这些详细的线程:

Enhanced Primitive Support (丰富的希基)

Clojure 1.3 treatment of integers and longs (内森·马兹)

关于types - 用于 Longs 的 Clojure 重载方法解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12586881/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com