我正在尝试使此高阶Kotlin函数起作用:
private inline fun <T> reentrant(entered: ThreadLocal<Boolean>, block: () -> T, enter: (() -> T) -> T) =
if (entered.get()) block()
else {
try {
entered.set(true)
enter(block)
} finally {
entered.set(false)
}
}
要像这样使用,例如:
reentrant(fooing, block) { b ->
try {
log("Entering a state of foo")
b()
// sidenote: while writing this question it dawned on me,
// that i could just calll the captured `block` here,
// as a workaround
} finally {
log("Foo nevermore")
}
}
但是,显然不允许构造enter(block)
(Illegal usage of inline parameter block
)。
由于这里的所有内容都是内联的,因此我认为在技术上应该是可能的。编译器仅不支持此功能吗?还是我有办法做到这一点?
答案 0 :(得分:1)
如果您执行类似val x = block
的操作,则会收到相同的错误。如果您尝试将Kotlin反编译为Bytecode,那么您将看到的最后一个错误是:
Trying to access skipped parameter
我想指出的是,当您内联某些内容时,它不再是代码中的对象,因此您不能直接引用它。显然,只需调用函数本身就可以,因为已将其内联到您的调用代码中。
对此进行更详细的说明here。内联函数参数时,不会创建Function
对象。我想知道您所隐含的含义是:“为什么编译器不内联enter
然后内联block
?而且我猜想原因是,这将假设所有enter
所做的都是调用block
。但是,如果没有呢?如果它想存储对它的引用怎么办?在将来某个时候调用的函数列表中?它无法执行此操作,因为没有Function
对象可供引用。