為什麼第三種寫法不對呢?
Swift 3.0 中,a++ 被廢除,print(a++) 這條代碼已經不合法,而 print( a += 1) 反而是合法的語句。
a += 1 是 a = a + 1 的簡寫,是賦值語句。賦值語句沒有返回值,或者說它的返回值是 ()。Swift 支持多返回值,當返回多個值時寫成 (a, b, c); 只有一個值時,寫成 a, 相當於 (a); 等沒有返回值時,就相當於 ()。
print( a += 1) 相當於 print( a = a + 1),相當於
a = a + 1
print(())
最終列印出 ()。
----------------------Swift 從語法設計上杜絕了一些 Objective-C 的坑,這些坑是從 C 語言延續過來的。
假如賦值語句有返回值。就可能將
if (a == 1) {
}
錯誤寫成
if (a = 1) {
}
在 C 語言中,為避免不小心寫錯,有時會寫成
if (1 == a) {
}
這種寫法被稱為 Yoda 表達式,因為《星球大戰》中的 Yoda 大師喜歡使用這樣奇特的倒裝句子。
Swift 語法上要求 if、while 後面判斷式子一定需要傳入布爾類型,並且賦值沒有返回值。寫成 if a = 1 就會編譯錯誤。Yoda 表達式這種變通寫法就沒有必要了。
Swift 3.0 中,去掉 a++,就不用再費神區分 a++ 和 ++a 的區別。也就不會出現 ++++a++++ 等於多少的無聊問題。
---------------------------
有些人或者覺得 if 中的語句是 Bool 類型,就已經解決了 if a = 1 的問題,賦值沒有返回值是不是太過分呢。但賦值就是賦值,本來就不應該有返回值。就算 if 中的語句強制是 Bool 類型,假如賦值有返回值,還是可以寫類似的坑人代碼。
if (x = y) &> 0 {
}
而假如 x 和 y 都是 Bool 值,也就可以寫成
if (x = y) {
}
另外還有
if x += 1 &> 0 {
}
甚至是
doSomething(x = y, y = z, z = x)
幸好在 Swift 中,這些代碼都不會再出現。有可能會犯的錯誤就一定有人會犯,就算犯過的人吸取了經驗不再犯了,還是會有源源不斷的新人會犯同樣的錯誤。靠 IDE 的 warning 是不管用的。
那賦值沒有返回值,會犧牲了什麼呢?只不過是將一行含糊的代碼拆兩行更確定的代碼。有些人可能會覺得這樣就不夠簡潔,但是在程序當中,簡潔並非指字元越少越好的。
這個問題,王垠寫過文章討論過。程序語言的常見設計錯誤(1) - 片面追求短小, 雖然他很多文章比較極端,但這篇文章我是認同的。
看函數+=聲明,沒有返回值,大部分人直覺都會認為是這個原因。真相可能是:恭喜你,找到了一個bug
public func +=(lhs: inout Int, rhs: Int) -&> Void
因為Void是typealias, a+=1的結果相當於 Void() ,而不是Void.
print(a+=1) 就相當於 print(Void())在xcode7.1中
print(Void()) //成功
print(a+=1) //出錯
我相信是因為Swift的未完善,而導致的Xcode的bug。不過好在Xcode升級到8.1後,官方已經解決。
類似的bug,print(Void)在Xcode8.1中不再支持(因為是typealias,說白了是Type )必須這樣:
//Xcode8.1
print(Void.self) //列印Type
print(Void()) //列印Value
其實解決條件表達式里 == 誤寫成 = 的方法就是要求條件的類型必須為 bool,這樣能篩掉大部分的錯誤。另外都2016年了這個老生常談的問題應該不會有太多人犯了,智能的 IDE 也基本會報 warning。放棄 a += 1 可以做 rvalue 的設計,有多少簡潔的代碼要分好多行,或者多定義幾個完全不必要的臨時變數來記錄中間值啊。
有點像當年 @Nullable Annotation 沒有引入的時候,一堆 Java 程序員發明了"A string literal".equals(fooVariable)
這種丑到爆的寫法,並號稱這樣的寫法能避免 fooVariable 是 null 的時候可能導致的 NullPointerException。一臉懵逼。你自己寫一個函數,裡邊用到的每個變數能不能是 null 你還不知道?寫成
fooVariable.equals("A string literal")
就是為了讓錯誤在更早的地方暴露出來,這樣修 BUG、分鍋的時候都有個依據。不然你按照前一種寫法湊合著跑下去了,然後把結果交給別的函數,別的函數里再出個別的錯誤,連錯誤地方都很難定位。
Swift 引入 Optional 的概念就是強製程序員時刻想清楚變數會不會是 null。
關於 null 為什麼是 Java 里最糟糕的設計之一,有很多文章都已經做了詳細的分析。如果想避免類似的問題的話,請使用基於 Apache License 2.0 的 Guava 里的 Optional&為什麼不更新一下 Xcode 呢?
a+=1等於a=a+1這個不能放在括弧里當參數用吧。你可以寫在外面當變數。
推薦閱讀:
※VS會不會成為移動開發首選?C#會不會崛起?
※舊的 iOS 應用該如何適配 iOS 7?
※App 的頻繁升級,會讓你覺得厭煩嗎?
※在Unity3D的Asset Store中賣插件有什麼值得分享的經驗?
※零基礎初學者如何學習製作APP?