蘋果新貴 Swift 之前世今生

本文的作者是中國《MacTalk·人生元編程》作者 池建強 ,來源微信公眾號「MacTalk By 池建強」。Inside 獲得授權轉載。
2010 年的夏天,Chris Lattner 接到了一
個不同尋常的任務:為 OS X 和 iOS 平台開發下一代新的程式語言。那時候賈伯斯還在以帶病之身掌控著龐大的蘋果帝國,他是否參與了這個研發計劃,我們不得而知,不過我想他至少應該知道此事,因為這個計劃是高度機密的,只有極少數人知道,最初的執行者也只有一個人,那就是 Chris Lattner。
從 2010 年的 7 月起,Chris 就開始了無休止的思考、設計、編纂程式和除錯,他用了近一年的時間實現了大部分基礎語言結構,之後另一些語言專家加入進來持續改進。到了 2013 年,該專案成為了蘋果開發工具組的重中之重, Chris 帶領著他的團隊逐步完成了一門全新語言的語法設計、編譯器、運行時、框架、IDE 和文檔等相關工作,並在 2014 年的 WWDC 大會上首次登台亮相便震驚了世界,這門語言的名字叫做:「Swift」。
根據 Chris 個人部落格 對 Swift 的描述,這門語言幾乎是他憑藉一己之力完成的。這位著名的 70 後工程師同時還是 LLVM 專案的主要發起人與作者之一、Clang 編譯器的作者,可以說 Swift 語言和 Chris 之前的軟體作品有著千絲萬縷的聯繫。
同樣是 70 後工程師,差別怎麼那麼大呢?
Chris 可以說是天才少年和好學生的代名詞,他在 2000 年本科畢業之後,繼續攻讀電腦碩士和博士。但 Chris 並不是宅男,學習之餘他手捧「龍書」遊歷世界,成為德智體美勞全面發展的好學生。之後就是一篇又一篇的發表論文,碩士畢業論文即提出了一套完整的運行時編譯思想,奠定了 LLVM 的發展基礎,就讀博士期間 LLVM 編譯框架在他的領導下得到了長足的發展,已經可以基於 GCC 前端編譯器的語義分析結果進行編譯優化和程式生成,所以 Chris 在 2005 年畢業的時候已經是業界知名的編譯器專家了。
作者注:很多電腦專業的大學生經常問我在大學裡學點什麼好,看看 Chris 就行了。以目前的科技資訊開放程度,如果你在自己感興趣的領域裡用心耕耘,再加上那麼一點點天分,畢業時成為某一個專有領域的專家應該不是問題。那時就不是你滿世界去找工作了,而是工作滿世界來找你!
Chris 畢業的時候正是蘋果為了編譯器焦頭爛額的時候,因為蘋果之前的軟體產品都依賴於整條 GCC 編譯鏈,而開源界的擁護者並不買蘋果的帳,他們不願意專門為了蘋果公司的要求優化和改進 GCC 程式,所以蘋果一怒之下將編譯器後端直接替換為 LLVM,並且把 Chris 招入麾下。 Chris 進入了蘋果之後如魚得水,不僅大幅度優化和改進 LLVM 以適應 Objective-C 的語法變革和性能要求,同時發起了 CLang 專案,旨在全面替換 GCC。這個目標目前已經實現了,從 OS X10.9 和 XCode 5 開始,LLVM+GCC 已經被替換成了 LLVM+Clang。
Swift 是 Chris 在 LLVM 和 Clang 之後第三個偉大的專案!
2007 年之前,Objective-C 一直是蘋果自家院落的小眾語言,但是 iOS 行動裝置的爆發讓這門語言的普及率獲得了火箭一般的竄升速度,截止到今天,Objective-C 在程式語言排行榜上排名第三,江湖人稱三哥,大哥二哥分別是 C 和 Java 這樣的老牌語言。同時,蘋果在 2012 年和 2013 年分別對 Objective-C 進行了大規模的優化和升級改進,增加了各種現代語言的特性,讓編寫 App 更加容易,更多的工程師投入到了 App Store 的生態圈裡……
在這種情況下,蘋果公司為什麼會發布一門新語言呢?
這個問題沒有標準答案,不過我們可以試著去分析一下,談談蘋果的心路歷程……
Objective-C 是 80 年代初 Brad Cox 和 Tom Love 發明的,1988 年賈伯斯的 Next 公司獲得了這門程式語言語言的授權,並開發出了 Objective-C 的語言庫和 NEXTSTEP 的開發環境。後來 Next 被蘋果收購,Objective-C 陰差陽錯成了蘋果的當家語言。掐指一算,三十年倏忽而過,OC 也成長為爺爺輩的程式語言了。
為了伺候好這位「爺爺」,蘋果煞費苦心,把 GCC 的編譯鏈先替換成 LLVM +GCC,又替換成 LLVM+Clang,做語法簡化、自動引用計數、增加 Blocks 和 GCD 多線程異步處理技術……終於,OC 在 30 年後重新煥發出勃勃生機,並佔據了兵器譜排名第三的位置。但是,蘋果卻有點煩了,OC 改進了這麼多年,怎麼看都像是在修修補補,用 Blocks 去實現一個類似 Python 的 lambda 閉包(closure)功能,看起來總是那麼彆扭。好吧,既然已經全盤掌握了 LLVM 和 Clang,為什麼我們不去基於現在的編譯器設計一門全新的語言呢?一門屬於蘋果的語言!你看,鄰居 Google 家裡叫做 Go 的孩子不是玩耍正酣嗎?
於是 Swift 誕生了……
當然,事實的真相也可能是行動緩慢的賈伯斯把 Chris 拉到一邊說:
「I want to be swift to……」
「行了,您別說了,不就是想要 swift 嗎,我這就給您做一個去」
於是 Swift 誕生了……
Swift 是一門博採眾長的現代語言,在設計的過程中, Chris 參考了 Objective-C、Rust、Haskell、Ruby、Python、C# 等優秀語言的特點,最終形成了目前 Swift 的語法特性。我在閱讀了官方教程和做了些程式實驗之後,自我感覺會喜歡上這門語言,在這裡簡單談點感想,更深入的內容需要你們自己去深入學習。
1. Swift 是針對 Cocoa 和 Cocoa Touch 的程式語言、編譯型語言,生產環境的程式都需要 LLVM 編譯成本地程式才能執行,但是 Swift 又具備很多動態語言的語法特性和互動方式。
2. Swift 是一門類型安全的語言,可以幫助開發者清楚的掌控程式片段中的值類型。如果你期望輸入的是字符串,類型安全的特性會阻止開發者錯誤地為其傳遞一個整數。這一切使得開發者能夠更早的發現和修復錯誤。
3. 支援各種高級語言特性,包括閉包、泛型、物件導向、多返回值、類型接口、元組、集合等。
4. Swift 能與 Objective-C 進行混合程式,但程式分屬不同的文件。
5. 全面的 Unicode 支持,你甚至可以用一隻「狗」作為變量名,實現以下操作:
let 狗 = “大狗菠蘿”
for n in 狗 {
println(n)
}
控制台會輸出「大狗菠蘿」四個字。
6. 程式語句取消了大部分語言使用的「;」分隔符,只有一行寫多條語句時才需要分號。
7. 很多人簡單閱讀了 Swift 的數據類型,就認為 Swift 沒有類似 Set、List 這樣的數據結構,其實 Swift 提供了兩種 Collection 的數據類型:Array 和 Dictionary,兩個數據類型的表達式都用中括號標識。其中數組可以存儲任意類型的變量,也可以強制聲明存儲同一種類型的變量。同時數組提供了類似 Set 功能,你可以修改、追加、替換和刪除數據的元素。另外,Swift 還提供了 Tuple 的功能支援函數多返回值。
8. Swift 沒有提供顯式的指針,參數傳遞根據數據類型的不同分為值類型和引用類型,值傳遞進行內存拷貝,引用傳遞最終傳遞的是一個指向原有對象的指針。這一點和 Java 的參數傳遞是類似的。需要注意的一點是,Swift 裡的數組和字典雖然都是結構體(struct),但在參數傳遞過程中處理方式卻不一樣,默認 Array 是引用傳遞,Dictionary 是值傳遞。而在 Java 中,由於數組和 Map 都是對象,所以傳遞的都是指針。
在 Swift 中,如果你不想傳遞數組引用,可以用 copy() 方法先複製一份出來,另外,也可以用 unshare() 表示,本變量不傳遞指針。
9. 閉包,Swift 終於提供了一種優雅的閉包解決方案,比如在排序函數 sort 中進行函數傳遞:
let names = ["D", "B", "R", "C", "A"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var rnames = sort(names , backwards)
事實上更簡單的寫法是:
var rnames = sort(["D", "B", "R", "C", "A"] ) {$0> $1 }
10. 可選變量(Optional)的引入主要是為了應對一個變量可能存在也可能是 nil 的情況,這種情況在很多高級語言裡都存在。比如你想使用 String 的 toInt 方法將 String 轉化為 Int 類型,但是你並不知道這個轉化是否正常,這時候系統會返回一個可選變量,如果轉換成功就返回正常值,轉換失敗就返回 nil,如下:
let str = “123A”
let nn = str.toInt()
這是 nn 就是可選變量,想得到 nn 的值,可以通過 if 進行判斷並藉著追加驚歎號獲取變量值,如下:
if nn {
println(nn!)
}
可選變量的引入解決了大部分需要顯式處理的異常,這部分工作也扔給編譯器去做了。想了解更多可選變量的用法,請閱讀蘋果的官方文檔。
11. Swift 中的 nil 和 Objective-C 中的 nil 不同。在 Objective-C 中,nil 是指向不存在對象的指針,而在 Swift 裡,nil 不是指針,它表示特定類型的值不存在。所有類型的可選值都可以被設置為 nil,不只是對像類型。
12. Swift 沒有從語言層面支持異步(Asynchronous)和多核,不過可以直接在 Swift 中復用 GCD 的 API 實踐異步功能。另外沒看到 Swift 的異常處理機制,可能有了可選變量,異常的使用會非常少吧。
關於語法相關的內容,先寫這麼幾點吧。
給大家推荐一篇王巍 (@onevcat) 寫的「行走於 Swift 的世界中」,深入閱讀必有收穫。
基本上,Swift 絕對不是玩具語言,而是一門可以被大眾接受的工業級程式語言。相信假以時日,Swift 必將在 App 開發領域大放異彩。
Swift 在 WWDC 上展示出來的性能還是讓人非常吃驚的,在進行複雜對象排序時,OC 的性能是 Python 的 2.8 倍,Swift 是 Python 的 3.9 倍;在實現 RC4 加密算法的時候,OC 的性能是 Python 的 127 倍,Swift 是 Python 的 220 倍。總之 Python 在某一個深坑里膝蓋中箭了,OC 也沒好到哪去,而 Swift,就是快啊就是快!
對於這一點我並不是很理解,首先是 WWDC 上展示的語言層面的基準測試過於簡單了,另外,OC 和 Swift 都是被 LLVM 編譯成本地程式執行的,理論上針對 Swift 的優化同樣可以應用於 OC,但是 Swift 居然比 OC 快那麼一點點,難道 LLVM 單獨針對 Swift 做了優化嗎?我表示不明覺厲(編按:中國網路用語,「雖然不是很明白,但是好像很厲害的樣子」縮寫)。
當然,還有更較真的工程師,他在第一時間針對於循環、遞增、數組、字符串拼接等功能進行了測試,發現 Swift 的性能比 OC 還是差那麼一點點的。
無論這些測試數據是否準確,我覺得性能是我們最不需要擔心的問題,蘋果已經全盤掌握了這個語言的方方面面,從底層編譯框架到編譯器再到語言設計,優化之路才剛剛開始,我們只要給這門新語言一點耐心就可以了。
對於開發者來說,Playground 是本次 WWDC 最大的亮點。能夠在編輯程式的同時實時預覽輸出結果是每個開發人員的夢想,這一次蘋果為大家提供了這樣的福利。
Playground 不僅實現了很多腳本語言支持的互動式程式,而且提供控制台輸出、實時圖形圖像、時間線(timeline)變量追蹤等功能,開發者除了可以看到程式的實時運行結果,還能根據時間線閱讀某個變量在程式片段中值的變化。這真是太棒了!
最初看到這個功能的時候我甚至以為每個 Swift 文件都可以基於 Playground 進行實時程式變化預覽,仔細閱讀文檔後發現,只能在 XCode 提供的 Playground 文件中實現以上功能。看來 Playground 顧名思義,目前還只是為開發者提供了一個玩耍程式的地方。
當然不只是玩耍,我們可以基於 Playground 做這些事情:
對於 Playground,設計者 Chris 是這樣描述的:Playground 功能傾注了我個人很多心血和激情,我希望新的程式語言具備更好互動性,更友好和有趣……我們希望通過這門語言重新定義「如何教授電腦科學!」
作為一門新語言,Swift 定位非常明確,就是吸引更多的開發者加入蘋果的軟體生態圈,為 iOS 和 OS X 開發出更為豐富的 App,如果你是 App Store 的開發者,推薦儘早學習和掌握這門蘋果力推的新語言。對於大部分新事物來說,越早介入,獲利越多。如果你是一名 Web 相關的開發者,與其等待 Swift 增加 Web 開發的相關特性,還不如去學習一下 Go
語言 Web 程式。
可以說 Swift 是我所見過關注度最高的新語言,一經推出即萬眾矚目,媒體和開發者在數天之內對 Swift 進行了長篇累牘的報導和討論,英文手冊迅速被翻譯成中文,即使是江湖上的另一位大佬谷歌 2009 年推出 Go 語言時也沒有如此浩大的聲勢。當然,這和 Go 語言的定位有關,作為一門系統級的伺服器端語言,開發者的可選餘地太大了,如果 Google 推出 Go 是用來取代 Java 開發 Android App,那可能情況就完全不一樣了。
經過 WWDC2014,蘋果已經完全體現出了一個軟體公司的創新能力和技術底蘊,無論是操作系統,程式語言,還是應用開發,蘋果都已經準備好了,凝神靜氣,蓄勢待發。作為開發者,我們要做的就是:Write the code, Change the world,然後期待下一個收穫的季節!