2016-11-30 68 views
1

我正在使用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() 

我不明白的第一件事就是爲什麼我需要的讓利塊內的回報。但它工作,所以我繼續前進。

我後來決定重構一些東西,使代碼的其他地方簡單,結束了這樣的事情:

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。我已經嘗試了多種變體,有沒有返回和地圖,讓和什麼。最接近的是序列<() - > Unit>的返回類型,它失敗了類型推斷。

任何人都可以解釋這裏發生了什麼?爲什麼這種類型不能被推斷?

+0

你讀過https://kotlinlang.org/docs/reference/lambdas.html嗎? 在第二種情況下,映射塊(lambda)中的最新表達式是返回值。在第一種情況下,你有所謂的「非本地返回」https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns – IRus

+0

我無法重構你的代碼,沒有指定所有類型和功能。如何發佈一個鏈接給你的代碼庫? – voddan

+0

不幸的是,我不能分享代碼庫。當我有時間時,我會嘗試在自包含的課程中編寫相關的代碼。 –

回答

2

returnmap lambda是一個非本地返回。它試圖從最接近的fun函數返回,這恰好是parseFileData

非本地回報率只從內聯函數,其拉姆達參數在調用點是內聯的允許,和map擴展Sequence不是一個內聯函數。

如果要從lambda本身返回一個值,請使用qualified return[email protected] ...或完全忽略它:然後塊中的最後一個表達式將作爲結果返回。