使用另一个内联lambda参数调用内联lambda

时间:2018-11-14 10:29:39

标签: lambda kotlin inline higher-order-functions

我正在尝试使此高阶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)。

由于这里的所有内容都是内联的,因此我认为在技术上应该是可能的。编译器仅不支持此功能吗?还是我有办法做到这一点?

1 个答案:

答案 0 :(得分:1)

如果您执行类似val x = block的操作,则会收到相同的错误。如果您尝试将Kotlin反编译为Bytecode,那么您将看到的最后一个错误是:

Trying to access skipped parameter

我想指出的是,当您内联某些内容时,它不再是代码中的对象,因此您不能直接引用它。显然,只需调用函数本身就可以,因为已将其内联到您的调用代码中。

对此进行更详细的说明here。内联函数参数时,不会创建Function对象。我想知道您所隐含的含义是:“为什么编译器不内联enter然后内联block?而且我猜想原因是,这将假设所有enter所做的都是调用block。但是,如果没有呢?如果它想存储对它的引用怎么办?在将来某个时候调用的函数列表中?它无法执行此操作,因为没有Function对象可供引用。