自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Swift 語言的設(shè)計(jì)錯(cuò)誤

開發(fā)
在『編程的智慧』一文中,我表揚(yáng)了 Swift 語言的 option type 設(shè)計(jì),但這并不等于 Swift 的設(shè)計(jì)是完美沒有問題的。其實(shí) Swift 1.0 剛出來的時(shí)候,我就發(fā)現(xiàn)它的 array 可變性設(shè)計(jì)存在嚴(yán)重的錯(cuò)誤。Swift 2.0 修正了這個(gè)問題,然而他們的修正方法卻仍然是錯(cuò)誤的。這個(gè)錯(cuò)誤一直延續(xù)到今天。

 在『編程的智慧』一文中,我表揚(yáng)了 Swift 語言的 option type 設(shè)計(jì),但這并不等于 Swift 的設(shè)計(jì)是***沒有問題的。其實(shí) Swift 1.0 剛出來的時(shí)候,我就發(fā)現(xiàn)它的 array 可變性設(shè)計(jì)存在嚴(yán)重的錯(cuò)誤。Swift 2.0 修正了這個(gè)問題,然而他們的修正方法卻仍然是錯(cuò)誤的。這個(gè)錯(cuò)誤一直延續(xù)到今天。

 

Swift 1.0 試圖利用 var 和 let 的區(qū)別來指定 array 成員的可變性,然而其實(shí) var 和 let 只能指定 array reference 的可變性,而不能指定 array 成員的可變性。舉個(gè)例子,Swift 1.0 試圖實(shí)現(xiàn)這樣的語義:

var shoppingList = ["Eggs", "Milk"]

shoppingList[0] = "Salad" // 可以對 array 成員賦值

let shoppingList = ["Eggs", "Milk"]

shoppingList[0] = "Salad" // 不能對 array 成員賦值,報(bào)錯(cuò)

然而這是錯(cuò)誤的。為了理解這個(gè)問題,首先你應(yīng)該清晰地區(qū)分 array reference 和 array 成員的區(qū)別。在這個(gè)例子里, shoppingList 是一個(gè) array reference,而shoppingList[x] 這樣的形式,是訪問一個(gè) array 成員。因?yàn)?var 和 let 本來是用于指定 shoppingList 這個(gè) reference 是否可變,也就是決定 shoppingList 是否可以指向另一個(gè) array。它并不能用于指定 array 成員的可變性。正確的用法應(yīng)該是這樣:

var shoppingList = ["Eggs", "Milk"]

shoppingList = ["Salad", "Noodles"] // 可以對 array reference 賦值

let shoppingList = ["Eggs", "Milk"]

shoppingList = ["Salad", "Noodles"] // 不能對 array reference 賦值,報(bào)錯(cuò)

var 和 let 只能有一個(gè)用途。它們一旦被用于指定 reference 的可變性,就不再能用于指定 array 成員的可變性。如果你理解 reference 是放在棧(stack)上的,而 Swift 1.0 的 array 是放在堆(heap)上的,就會明白 var 和 let 其實(shí)只能指定棧上數(shù)據(jù)的可變性。堆上的數(shù)據(jù)可變性,必須用另外的方式來指定。

實(shí)際上很多語言都已經(jīng)看清楚了這個(gè)問題。C++ 程序員都知道 int const * 和int * const 的區(qū)別。Objective C 程序員都知道 NSArray 和 NSMutableArray 的區(qū)別。我不知道為什么 Swift 的設(shè)計(jì)者看不到這個(gè)問題。

Swift 2.0 修正了這個(gè)問題,可是它的修正方法卻是錯(cuò)誤的:它把 array 從 reference type 變成了所謂 value type,也就是說把 array 放在棧上,而不是堆上。這貌似解決了以上的問題,因?yàn)橛捎?array 是棧數(shù)據(jù), shoppin List 不再是一個(gè) reference,而是代表 array 的數(shù)據(jù)本身,所以你確實(shí)可以用 var 和 let 來決定它是否可變。

這看似一個(gè)可行的解決方案,然而它卻沒有擊中要害,它帶來了另外的問題。把 array 作為 value type,使得每一次對 array 的賦值或者參數(shù)傳遞,都必須進(jìn)行拷貝。你沒法使兩個(gè)變量指向同一個(gè) array,也就是說 array 不再能被共享。

這違反了程序員對于數(shù)組這種大型結(jié)構(gòu)的“心理模型”,他們不再能清晰方便的對 array 進(jìn)行思考,容易犯錯(cuò)誤。而且對數(shù)組的拷貝需要大量時(shí)間,對效率有很大影響。沒有任何另外的現(xiàn)代語言(Java,C#,……)把 array 作為 value type。

實(shí)際上如果你看透了它的實(shí)質(zhì),就會發(fā)現(xiàn) value type 這東西的存在,其實(shí)是沒有意義的。眾多的新語言,Swift,Rust 試圖利用 value type 之類來解決內(nèi)存管理的效率問題,然而它帶來的好處是微乎其微的,給程序員帶來的麻煩和困擾卻是有目共睹的。

從 Swift 的設(shè)計(jì)犯下這樣的低級錯(cuò)誤,你也許可以看出來,編譯器專家并不等于程序語言專家。很多程序語言專家一看到 Swift 最初的 array 設(shè)計(jì),就知道那是錯(cuò)的。為什么 Swift 的設(shè)計(jì)者直到 1.0 發(fā)布都沒有發(fā)現(xiàn),到了 2.0 修正卻仍然是錯(cuò)誤的呢?我猜這是因?yàn)?Apple 并沒有聘請合格的程序語言專家進(jìn)行 Swift 的設(shè)計(jì)。Swift 的***設(shè)計(jì)師是 Chris Latner,也就是 LLVM 的設(shè)計(jì)者。Chris Latner 是一個(gè)不錯(cuò)的編譯器專家,然而他卻只能算是業(yè)余級別的程序語言設(shè)計(jì)師。編譯器和程序語言,真的是兩個(gè)非常不同的領(lǐng)域,不要盲目的以為好的編譯器作者就能設(shè)計(jì)出好的程序語言。

由于沒有招募到深入精髓的設(shè)計(jì)師,自己瞎倒騰,使得 Swift 語言團(tuán)隊(duì)犯下根本不該犯的錯(cuò)誤。***次就應(yīng)該做對的事情,卻需要經(jīng)過很多次的返工。以至于每出一個(gè)新的版本,就出現(xiàn)很多“breaking change”,導(dǎo)致之前版本的 Swift 代碼不再能用。這種情況對于 Swift 語言并不是世界末日,然而我希望 Apple 能夠早點(diǎn)招募真正的語言設(shè)計(jì)專家,采納他們的建議。

責(zé)任編輯:趙立京 來源: 王垠
相關(guān)推薦

2015-04-17 16:07:11

swiftOC

2014-06-03 10:44:20

Swift開發(fā)語言

2014-06-04 10:52:56

Swift蘋果iOS

2015-08-14 11:37:37

Swift語言中文版

2014-08-01 15:16:05

SwiftC語言

2015-06-09 11:12:31

Swift語言Swift特性

2014-06-26 10:21:04

Material DeSwift

2015-12-04 13:57:09

Swift編程設(shè)計(jì)準(zhǔn)則

2016-08-19 10:41:42

Swift 2錯(cuò)誤

2021-04-29 09:02:44

語言Go 處理

2014-11-17 10:05:12

Go語言

2017-09-25 14:22:26

Swift4.0正式發(fā)布添加歸檔

2023-03-10 09:00:49

Swift開發(fā)者工具

2015-01-12 13:04:39

Swift開源項(xiàng)目匯總

2015-12-07 09:46:26

swift編程開源

2010-01-22 10:26:40

C++語言

2020-10-19 09:34:04

C語言內(nèi)存錯(cuò)誤編程語言

2018-03-11 08:30:32

Swift 編程語言C語言

2024-01-04 07:49:00

Go語言方法

2014-06-06 14:25:03

iOS 8SwiftWWDC2014
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號