2017-06-14 35 views
6

我正在學習新的非常漂亮的Kotlin語言,並且所有內容似乎都非常符合邏輯和一致。我只發現了一件看起來像規則的任意例外情況,而不是一條堅實的規則。但也許我缺乏足夠的理解背後的一些深層原因。返回塊中的最後一個表達式

我知道在if-elsewhen語句中有代碼塊,然後返回最後一個表達式。在下一個示例中,根據條件返回12 - 在我們的情況下返回1

val x = if (1 < 2) {println("something"); 1} else {println("something else"); 2} 

另一方面,這不適用於任何代碼塊。下一行代碼y不是1,而是整個代碼塊作爲lambda。

val y = {println("something"); 1} 

類似地,在函數體中,不會返回最後一個表達式。這甚至沒有編譯。

fun z() : Int { 
    println("something") 
    1 
} 

那麼究竟是什麼規則?它是否真的如此隨意:如果在用作表達式的if-elsewhen語句中有一段代碼,則返回該塊中的最後一個表達式。否則,最後一個表達式不會返回到外部作用域。或者我錯過了什麼?

回答

4

你誤會了大括號{},當週圍所有flow-control聲明,這只是一個,例如:

if (condition) { //block here 
} 

WHEN{}分別宣稱它是一個拉姆達表達,例如:

val lambda:() -> Int = { 1 }; // lambda 

WHEN要返回lambdaif-else表達式,則必須雙大括號{}或使用括號()拉姆達表達之間的區別,或使{}爲lambda明確,例如:

val lambda1:() -> Int = if (condition) { { 1 } } else { { 2 } }; 
val lambda2:() -> Int = if (condition) ({ 1 }) else ({ 2 }); 
val lambda3:() -> Int = if (condition) { -> 1 } else { -> 2 }; 

如果一個函數不返回任何有用的價值,它的返回類型是UnitUnit是隻有一個值的類型 - Unit。此值不必返回明確

在另一方面,共同function必須有一個明確的return聲明,如果它的返回類型不是Unit

fun z(): Int { return 1; } 

另一種情況是一個函數返回Nothingreturn聲明唐完全不允許,因爲你無法創建一個Nothing實例,例如:

fun nothing(): Nothing { 
    return ?;// a compile error raising 
} 

WHEN的功能只有一個表達式,那麼你可以使用single-expression function代替,例如:

fun z() = 1; 
+1

是的,這可能是我的意思通過我的評論。 '{}'有三個(甚至更多?我錯過了一些?)不同的角色 - 它可以是控制流語句中的一個塊,也可以是lambda或它可以是一個函數體。不同的規則適用於所有這些情況。我不是故意咆哮或抱怨,我必須承認它。但是,在我看來,這是一種不完美的語言的不一致的語言設計缺陷。 –

+0

@ V.K。是的先生。你是對的。 –

+1

我的編碼風格從這個問題中解脫出來,是我將盡量避免控制流語句中的塊用作表達式時。我來自C++和Python領域,沒有什麼比'返回塊中的最後一個表達式',所以只有當返回的表達式不重要時(例如沒有塊),我纔會使用if或者when作爲表達式。 'a = if(x)y else z'。否則,我將使用全面的語法if(x){println(「something」); a = y} else {println(「別的東西」); a = z}'就像我們從其他語言那裏知道的一樣。 –

2

有一個lambda塊,只是一個「正常」的塊之間的差異,你的情況「Y 「僅僅是需要執行去得到返回的值拉姆達:

val block:() -> Int = { 5 } 
val five: Int = { 5 }() 
val anotherFive = block() 

所以,如果你想充當拉姆達塊,你可以創建一個lambda並執行它,可以立即‘()’ 。這樣一來,你的「Z」功能將編譯如下所示:

fun z() : Int = { println("something") 1 }()

(其中,當然,沒有多大意義,是不是很有效)

相關問題