【问题标题】:Type inference with functional builders使用功能构建器进行类型推断
【发布时间】:2016-11-30 21:59:37
【问题描述】:

我正在使用 Kotlin KBuilders 和一些 protobuffs,遇到了让我困惑的情况。

首先,我有一个函数,它接受文件名和序列化 JSON 列表并将该 JSON 反序列化为 protobuff。

fun parseFileData(fileName: String, lines: List<String>): Data.Builder.() -> Unit = when (fileName) {
        SOME_FILE_NAME -> deserializeLinesToModel(lines, DataModel::class.java)
                .let {
                    return {
                        dataMeasurement = buildDataMeasurement {
                            property1 = it.reduce { acc, n -> acc + n }
                            measurementMsec = it.map { it.measurementMsec }
                        }
                    }
                }
        else -> throw UnsupportedOperationException()

我不明白的第一件事是为什么我需要在 let 块中返回。但它奏效了,所以我继续前进。

我后来决定重构一些东西以使其他地方的代码更简单,最终得到了这样的结果:

fun parseFileData(fileName: String, factory: DataFactory): Sequence<Data.Builder.() -> Unit> = when (fileName) {
        SOME_FILE_NAME -> factory.getSomeFileSequence() // returns Sequence<Model>
                                .batch(1000) // process data in batches of 1000 to reduce memory footprint and payload size 
                                .map { return {
                                            dataMeasurement = buildDataMeasurement {
                                            property1 = it.reduce { acc, n -> acc + n }
                                            measurementMsec = it.map { it.measurementMsec }
                                    }
                                }
        else -> throw UnsupportedOperationException()

所以基本上,我没有将每个批次作为一个列表进行处理,而是从工厂读取序列,将其批处理为一系列列表并尝试将每个列表映射到Data.Builder.() -&gt; Unit。但是,这次我得到了return is not allowed here。我尝试了多种变体,有和没有 return 和 map 和 let 等等。我得到的最接近的是 Sequence Unit> 的返回类型,它失败了类型推断。

谁能解释这里发生了什么?又为什么不能推断出这种类型?

【问题讨论】:

  • 你读过kotlinlang.org/docs/reference/lambdas.html 吗?在第二种情况下,地图块(lambda)中的最新表达式是返回值。在第一种情况下,您有所谓的“非本地返回”kotlinlang.org/docs/reference/…
  • 如果不指定所有类型和函数,我将无法重构您的代码。发布一个指向你的代码库的链接怎么样?
  • 很遗憾,我不能共享代码库。有时间我会尝试将相关代码写在一个独立的类中。

标签: kotlin type-inference


【解决方案1】:

map lambda 中的return 是非本地返回。它尝试从最近的fun 函数返回,恰好是parseFileData

仅允许内联函数进行非本地返回,其 lambda 参数在调用站点内联,Sequencemap 扩展不是内联函数。

如果你想从 lambda 本身返回一个值,使用 qualified return return@map ...,或者完全省略它:那么块中的最后一个表达式将作为结果返回。

【讨论】:

    猜你喜欢
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 2019-04-10
    • 2020-01-08
    • 2012-11-13
    • 1970-01-01
    • 2022-11-07
    • 1970-01-01
    相关资源
    最近更新 更多