我使用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.() -> Unit
。但是,这次我得到return is not allowed here
。我尝试了多种变体,包括和不使用返回和地图以及let和whatnot。我最接近的是Sequence&lt;() - &gt;的返回类型。单元&gt;没有类型推断。
有人能解释一下这里发生了什么吗?为什么不能推断出这种类型?
答案 0 :(得分:2)
return
lambda中的 map
是非本地回报。它会尝试从最近的fun
函数返回,该函数恰好是parseFileData
。
非本地返回仅允许来自内联函数,其lambda参数在调用站点内联,而map
的{{1}}扩展名不是内联函数。
如果要从lambda本身返回一个值,请使用qualified return Sequence
,或者完全省略它:然后将返回块中的最后一个表达式作为结果。