Wil*_*oom 2 primitive lambda inline kotlin
我正在编写一个 Kotlin内联类,以使Decimal4J更方便,而无需实例化任何对象。我担心作用域函数可能会创建 lambda 对象,从而使整个事情变得毫无意义。
compareTo考虑以下示例中的函数。
/* imports and whatnot */
@JvmInline
value class Quantity(val basis: Long) {
companion object {
val scale: Int = 12
val metrics: ScaleMetrics = Scales.getScaleMetrics(scale)
val arithmetic: DecimalArithmetic = metrics.defaultArithmetic
}
operator fun compareTo(alt: Number): Int {
with(arithmetic) {
val normal = when (alt) {
is Double -> fromDouble(alt)
is Float -> fromFloat(alt)
is Long -> fromLong(alt)
is BigDecimal -> fromBigDecimal(alt)
is BigInteger -> fromBigInteger(alt)
else -> fromLong(alt.toLong())
}
return compare(basis, normal)
}
}
}
Run Code Online (Sandbox Code Playgroud)
作用域是否with(arithmetic)在堆中创建 lambda?kotlinlang.org 上的文档一致将作用域代码称为 lambda 表达式。有没有办法在不创建对象的情况下使用作用域函数?
所有内置作用域函数(包括 )都with被标记为inline,这意味着实现直接植入到调用它的代码中。一旦发生这种情况,就可以优化 lambda 调用。
更具体地说,这是(删除了 Kotlin 合约内容,因为这与此处无关)的实现with
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
Run Code Online (Sandbox Code Playgroud)
扩展方法始终是在编译时解析的语法糖,因此这实际上是有效的
public inline fun <T, R> with(receiver: T, block: (T) -> R): R {
return block(receiver) // (with `this` renamed by the compiler)
}
Run Code Online (Sandbox Code Playgroud)
所以当我们打电话时
operator fun compareTo(alt: Number): Int {
with (arithmetic) {
println("Hi :)")
println(foobar()) // Assuming foobar is a method on arithmetic
}
}
Run Code Online (Sandbox Code Playgroud)
将把inline它变成
operator fun compareTo(alt: Number): Int {
({
println("Hi :)")
println(it.foobar()) // Assuming foobar is a method on arithmetic
})(arithmetic)
}
Run Code Online (Sandbox Code Playgroud)
任何称职的优化器都可以看到这是一个立即评估的函数,因此我们应该立即执行此操作。我们最终得到的是
operator fun compareTo(alt: Number): Int {
println("Hi :)")
println(arithmetic.foobar()) // Assuming foobar is a method on arithmetic
}
Run Code Online (Sandbox Code Playgroud)
这就是你一开始应该写的。
所以,tl;dr,编译器足够聪明,可以解决这个问题。你不必担心它。这是使用高级语言工作的好处之一。
顺便说一句,这不仅仅是抽象的。我只是在自己的机器上编译了上面的代码,然后反编译了 JVM 字节码,看看它到底做了什么。它的噪音相当大(因为 JVM 必然有很多噪音),但没有分配 lambda 对象,并且该函数只是一次调用println两次的直接调用。
如果您有兴趣,Kotlin 采用此示例函数
fun compareTo(alt: Number): Unit {
return with(arithmetic) {
println("Hi :)")
println(foobar())
}
}
Run Code Online (Sandbox Code Playgroud)
对于这个Java,反编译后,
public static final void compareTo-impl(long arg0, @NotNull Number alt) {
Intrinsics.checkNotNullParameter((Object)alt, (String)"alt");
long l = arithmetic;
boolean bl = false;
boolean bl2 = false;
long $this$compareTo_impl_u24lambda_u2d0 = l;
boolean bl3 = false;
String string = "Hi :)";
boolean bl4 = false;
System.out.println((Object)string);
int n = so_quant.foobar-impl($this$compareTo_impl_u24lambda_u2d0);
bl4 = false;
System.out.println(n);
}
Run Code Online (Sandbox Code Playgroud)
虽然有点吵,但想法是完全一样的。所有这些无意义的局部变量都将由一个好的JIT 引擎处理。
| 归档时间: |
|
| 查看次数: |
495 次 |
| 最近记录: |