2016-11-01 29 views
4

在斯威夫特,你可以,如果讓可選的結合解開可選成常量或變量具有相同名稱的使用。爲什麼不讓警衛foo = foo有效?</p> <pre><code>func test() { let a: Int? = 1 if let a = a { print("a = (a)") } } </code></pre> <p>對於<code>if let</code>語句中的一切,可選<code>a</code>被解開成常規INT:

同樣,我可以用一個後衛語句來達到類似的效果

func test() 
{ 
    let a: Int? = 1 

    guard let requiredA = a else{ 
    return 
    } 
    print("a = \(requiredA)") 
} 

但是,我不能用這樣的代碼:guard let a = a else

func test() 
{ 
    let a: Int? = 1 

    guard let a = a else{ 
    return 
    } 
    print("a = \(a)") 
} 

爲什麼不呢?

在guard語句中,如果guard語句的條件失敗,則會執行else子句並退出當前作用域。如果條件成功,則從guard語句的右大括號到當前作用域的末尾創建一個新變量/常量。

爲什麼我不能用相同的方法將可選項映射到當前範圍其餘部分的同名變量/常量?

措施:我意識到這個問題不是一個完美的適合這個網站。我很樂意提出有關這個問題的更好的地方。

+1

在我看來,'if'方法在不同的作用域中創建了兩個變量,這很好,而'guard'方法會在同一個作用域中創建兩個相同名稱的變量,這將是一個奇怪的特例,使可變分辨率規則複雜化以允許它。不過,我猜測,我不知道斯威夫特。 – user2357112

回答

10

的原因,你不能做到這一點:

func test() 
{ 
    let a: Int? = 1 

    guard let a = a else{ 
    return 
    } 
    print("a = \(a)") 
} 

是因爲guard會在同一範圍內的新變量,因此你有兩個變量在同一範圍內名爲a。一個是Int,另一個是Int?。這是不允許的。

,你得到與前值定義衝突的錯誤是完全一樣的,如果你做了這一點:

func test() 
{ 
    let a: Int? = 1 

    let a = a! 
} 

相比之下,與:

func test() 
{ 
    let a: Int? = 1 

    if let a = a { 
     print("a = \(a)") 
    } 
} 

在這情況下,新變量a這是一個Int只存在於的新範圍的條款,所以這個作品。


從評論:

But I submit to you that the section of code after the closing brace and to the end of the enclosing scope is actually an inner scope.

我可以理解,你想它是這樣,但事實並非如此。如果是這樣的話,那麼你可以做到這一點,但它也提供了一個錯誤:

func test() 
{ 
    let a: Int? = 1 

    guard let b = a else{ 
     return 
    } 
    print("b = \(b)") 

    let a = 5 // Definition conflicts with previous value 

    print("a = \(a)") 
} 

guard美妙之處在於它不創造新的領域,你要避免使金字塔死亡的那當您重複使用if let打開可選項(並在創建新範圍的過程中)時會出現結果。


見後續問題 When did guard let foo = foo become legal?關於這一主題更深入的瞭解。

+0

但我向你提出,在右括號和封閉範圍的末尾之後的代碼段實際上是一個內部範圍。如果你創建一個新的變量/常量,它從那個點開始直到當前作用域結束。這與'if let'有什麼區別,在語句的主體內部,'a'的局部定義是否會覆蓋外部定義? –

+0

它不同於'if let',因爲'如果讓''後面的'{}'如果let'創建一個新的範圍。 「警衛」的美妙之處在於你沒有「{}」,從而避免了新範圍的死亡金字塔。 – vacawama

+0

@DuncanC'如果let'完全不同。試試這個:'如果讓b = a {...}讓b = 4'。第二個'b'很好,因爲'if let'中的'b'不在範圍之內。 – rmaddy

相關問題