一派胡言!Swift 不是多範式函數式程式語言

2020-12-20 CSDN

來源 | Cocoaphony

譯者 | 蘇本如,責編 | 夕顏

封圖 | CSDN下載自視覺中國

自從Swift問世以來,我一直看到一些奇怪的評論,認為Swift是一種函數式程式語言。我有點納悶為什麼有人會這麼說,因為Swift幾乎沒有什麼「函數」。它是一種非常傳統的面向對象語言,著重於泛型編程。

我的推測是,人們使用一個特性列表來確定一種語言的範式。但我們使用範式這個詞是有原因的。

範式——以某一特定科學科目的理論和方法論為基礎的一種世界觀。

「一種世界觀。」是的,這就是它的本質所在。

程式語言範式很像音樂流派。它們是混亂的東西,我們可以爭論在哪裡畫線,什麼去哪裡,什麼是純粹的以及什麼是融合。但就像古典吉他和重金屬屬於不同的流派一樣,即使他們都使用吉他。

我有些朋友說他們對音樂很有鑑賞力。他們標榜自己聽「一切」的音樂。從Jimmy Buffet的鄉村搖滾到Metallica的重金屬音樂,這些樂隊演奏的所有音樂他們都喜歡。許多程式設計師也是如此。他們只知道過程編程和面向對象編程的範式。他們認為BASIC和Java之間的區別就是所有語言之間的區別了。當他們遇到一種新的語言時,他們的第一個問題是「它的語法是什麼?」?但是我認為他們的問題應該是「它是如何看待問題的?」

我現在要說很多關於編程範式的事。像音樂流派一樣,有很多觀點和方法可以對音樂進行分類。我的方法不是唯一的方法。但是有些方法比其他方法更加有用。我想表達的是,因為它們都有map而將Swift和Haskell歸為一類程式語言的分類法,並不比因為它們都有vocalists而將Wangga、Opera、和Rock歸為一類程式語言的分類法更有用處。

過程式(或命令式)編程主要關注的是將問題分解為一系列的動作。它通常的結構是「執行第一步,然後重複執行第二步,直到某件事是真的,然後執行第三步。」這種範式在流行的程式語言中非常普遍,以至於許多程式設計師認為這就是編程的全部意義。這當然不是。它只是分解問題的一種方法。當面對一個問題時,過程式編程的問題是:「我需要執行哪些步驟來解決這個問題?」

面向對象編程(OOP)主要關注的是將問題分解為具有屬性的自包含對象,以及操作這些屬性的方法的集合。它通常的結構是帶有實例(對象)的類的層次結構,這些實例繼承了屬性和方法。當面對一個問題時,面向對象編程的問題是「需要什麼樣的對象一起工作才能解決此問題?」

這兩種思維方式在流行的程式語言中極其普遍,並且可以很好地協同工作。自從第一批機器語言問世以來,過程式編程就一直伴隨著我們。即使是早期的自動織布機也是在過程式範式下工作。

自上世紀90年代以來,面向對象編程(OOP)一直是編程的主導。長期以來,它一直是主流的範式,並且一直長時間地主導著CS程序,以至於許多程式設計師都認為這是必然的。他們認為只有像Fortran這樣的「古老語言」才會缺乏對象(而現在,甚至連Fortran都支持對象了)。

但是面向對象編程(OOP)只是思考問題的一種方式。函數式編程是思考問題的另一種方式。函數式編程主要是將問題分解為接受並返回不可變值的函數。它通常的結構是一些將值轉換為其他值的函數,以及各種組合函數的方法的集合。它避免了可變狀態,並且不要求函數的求值以任何特定的順序進行。函數式編程將程序視為一個數學問題,而不是一系列操作。當面對一個問題時,函數式編程的問題是「需要以何種方式來轉換什麼樣的值以解決此問題?」

當你第一次開始使用Swift時,你首先要找的是什麼?也許是它如何處理類和協議的?也許是如何調用方法,聲明和分配變量,定義屬性?或者是它們的for和while循環版本?這些都是面向對象編程和過程式編程的工具,你認為它們都是容易獲得和易於使用的,這是正確的。你只需要知道語法。

我聽到有人將Swift描述為「函數式的」,因此,當我打開我的第一個Swift工作區時,我立即查找Swift中的flatmap的用途。我想知道它是怎麼用來將一個列表拆分為頭和尾的。我查找了一個foldLeft等效且不可變的集合。Swift似乎對它們都沒有進行特殊處理。這並不是說一門語言必須具有這些才能被稱之為函數式語言,就像一門語言必須具有for循環才能被稱為過程式語言一樣。

但是,如果我向你展示了一種新語言,並且說它是面向過程和面向對象的,但是你必須使用if和goto來實現for循環的功能,並且沒有類繼承,那麼你可能會對這種語言的特性選擇感到驚訝。一個無法在O(1)時間內簡單地將一個列表折分出「第一個」和「不是第一個」元素的「函數式」語言是一種非常奇怪的函數式語言。

Swift特有reduce和map函數,它還具有第一類函數和模式匹配。並且,它還具有在其它函數式語言中也很常見的一些特性。它的語法甚至感覺與Scala非常相似(當我意識到關聯值是樣式類(case class)時,關於它們的一切就變得有意義了)。但是它並不像其它函數式語言那樣思考問題。它們鼓勵你在任何可能的地方使用let,但是在一個Swift程序中,你總是會有let和var的混合,並且蘋果提供的大多數示例都包含變量。在Scala中工作時,我幾乎從不使用可變變量。在Haskell中,可變變量被認為是高級功能,甚至都沒有出現在介紹性的書籍中。

這就給我們帶來了真正的差異。在Swift中,你基本上是以一個過程式編程/面向對象編程的範式進行工作,並且整個語言都是圍繞這個範式構建的。當有需要時,有一些工具可以讓你跳到函數編程樣式(但沒有函數式編程的全部功能)。在Haskell中,你基本上是以函數式編程的範式進行工作。有一些可用的工具(Monad)可以讓你在需要過程編程樣式(沒有過程編程的全部功能)時,跳轉到它。

有人可能會說:「Rob,你太直白了。Swift是一種多範式語言,它包含了面向對象編程和函數式編程。」這是一派胡言。Scala才是一種多範式的,面向對象編程/函數式編程。當你在Scala中處理一個問題時,你將其分解為主要在不可變數據結構上工作的對象。這才是面向對象編程/函數式編程的做法。而在Swift中,他們甚至連提供一個不可變列表都不願意。並不是說他們無法添加它,而是因為這並不是Swift工作的根本。

Swift是一個多範式程式語言,但它不是面向對象/函數式編程的。而是面向對象/泛型編程的。泛型編程主要關注可應用於任意類型的通用算法。它與函數式編程有一些相似之處,當然也有這樣的程式語言,它既是函數式的,又是泛型的,但是泛型編程不在乎算法是函數(接受並返回不可變值的東西)還是過程(改變狀態的事物)。你可以說Swift不是泛型的,因為它有Array<Int>(整形數組)。你可以用非泛型語言實現這種結構。你也可以說Swift是泛型的,因為你可以在整個核心庫中找到泛型編程的程序。考慮像advance這樣的函數:

/// Return the result of moving start by n positions. If T models/// RandomAccessIndex, executes in O(1). Otherwise, executes in/// O(abs(n)). If T does not model BidirectionalIndex, requires that n/// is non-negative.func advance<T : ForwardIndex>(start: T, n: T.DistanceType) -> T

這正是你對泛型語言所期望的那種功能。它封裝了一種算法,該算法可以在任何實現ForwardIndex的對象上工作。但它不是ForwardIndex實例繼承或必須實現的方法。這似乎很微妙,但實際上是一種截然不同的思維方式。

你可以在Swift標準庫中看到很多這樣的東西,它們正是你希望在泛型語言中找到的東西。很多看起來像「函數」特性的東西實際上只是通用的算法。讓我們看看下面的quickSort和reduce函數:

func quickSort<C : MutableCollection where C.IndexType : SignedInteger> (inout elements: C, range: Range<C.IndexType>, less: (C.GeneratorType.Element, C.GeneratorType.Element) -> Bool)func reduce<S : Sequence, U>(sequence: S, initial: U, combine: (U, S.GeneratorType.Element) -> U) -> U

reduce是一個非常常見的函數工具,它就在quickSort函數旁邊,但是沒有函數式語言會以這種方式公開它(它改變了集合)。兩者都以泛型樣式表示。它們只是算法。一個可以改變集合,另一個不可以。重要的是算法可以在多種數據上重複使用,這就是泛型編程。我們得到了一些函數特性,但這其實只是它的一個副作用,而不是它的範式。

這些都不是對Swift的批評。沒關係,它不是函數式語言。我本來想,要是所有Cocoa開發都是函數式編程就好了,但這只是因為我喜歡它。我不知道這是否會進一步實現真正出色的iOS和Mac應用程式的目標(至少在短期內)。不是說FRP(函數響應式編程)不是個好主意。對此我沒有什麼強烈的意見。只是與Swift.2相比,ObjC程式設計師的學習曲線很高2,而我們需要將Swift與(非函數式的)ObjC集成很長一段時間。

我希望隨著時間的推移,Swift將會包含更多的函數特性。if和switch應該返回值。應該允許在模式匹配中將一個列表拆分成頭和尾(這點應該很輕鬆就能實現)。函數應該接受具有強制尾調用優化的「尾遞歸」屬性。可變方法應該很少用,不可變的數據類型應該更多。

這些東西都不會使得Swift自己成為函數式語言。但是足夠多的這些東西可以讓我們用更多的函數功能模式來編寫代碼,也許有朝一日,Swift和Cocoa可以真正成為函數式程式語言。如果這是最終的結果,那麼Swift可能會成為一門出人意料的重要語言,它可以改進編程規程,因為程式設計師必須學習函數式編程才能在一個非常流行的平臺上開發。學習函數式編程可以讓你成為一個更好的程式設計師,即使你使用其他範式工作。

或者這些都不會發生,Swift可能只是一種編寫非常出色的iOS和Mac應用程式的語言,但這也沒關係。

我相信所有這些東西在Swift中實現都會非常簡單。但是他們並沒有跳出文檔的框框,甚至在任何Swift視頻中都沒有討論過這些內容。這是一種對什麼是重要的和什麼是可能的一種衡量。它們會告訴你所用的範式。我在Scala中進行反應式UI編程的經驗好壞參半。即使有函數式編程的背景,我發現我的學習曲線仍然很高,並且程序很難調試。但這可能只是需要更多的經驗。這似乎是個好主意,我只是不知道它是否真的是個好主意。我以前騎摩託車。當你騎摩託車的時候,你必須比開車的時候更加清醒。否則,你會受傷的。但是我注意到的是,騎摩託車使我成為了更好的汽車駕駛員。函數式編程就是這樣。騎摩託車不一定是到達目的地的最佳方式,但是如果每個人都學會了騎摩託車,我們會擁有更好的駕駛員。如果大學先教Haskell,然後再教Java,我們就會有更好的程式設計師。

原文連結:https://robnapier.net/swift-is-not-functional

本文為CSDN翻譯文章,轉載請註明出處。

【END】

相關焦點

  • 函數式編程中的副作用概念
    前言為了清楚起見,請記住,副作用不是必需的壞事,有時副作用是有用的(尤其是在函數式編程範式之外)。今天聊一聊函數式編程中的隔離思想,它所想隔離的就是「副作用」我們先從其他角度來聊一聊副作用這個概念。當你寫下這個函數之後,你的餘生都可以放心使用它,無論上下文如何,它將永久有效。永恆的東西變化的頻率較低,測試起來更加容易,調試起來更加容易。這就是為什麼現在很多程式語言都傾向於無副作用。
  • 自創一門程式語言的14步
    自創一門程式語言的14步 現在,很多人對他們現在每天使用的程式語言感到困惑和不解,他們都有各自的需求,無論你是一名職業的 IT 人員還是普通的開發愛好者,你可能想要創造一門新的程式語言。下面就來告訴你如何創造一門程式語言。
  • 《奇葩說》第七季第七期的「一派胡言」環節,金句頻出!
    李誕:一派胡言,那可不是一點兒數。 2 三十歲掙那麼點數,難道你心裡不愧疚嗎? 李誕:一派胡言,我怎麼會不愧疚呢?我20歲就應該掙這麼多的。 3人醜就要多讀書!
  • C語言編程技巧:如何在函數中正確返回字符串的指針
    問題提出在C語言編程中,我們經常會遇到這種情況,在某個函數中經過算法處理以後得到一個字符串類型的結果,可能需要將這個字符串以指針的形式進行返回,那麼如何在函數中正確返回該字符串的內容呢?,我們知道,這個字符串「I love C.」存放在整個程序的常量區,而並不是getString2的局部變量,也就是說,在程序整個的運行周期內,該字符串「I love C.」常量始終存在,並不會因為函數調用的結束而消失。所以,指針變量p雖然是一個局部變量,但p本身的值僅僅是一個4個字節的指針地址值,這個地址值也就是「I love C.」的字符串的地址值。
  • 看看9種程式語言的發明者是怎麼說的
    Dahl:Node與其他的語言有一點明顯的區別,就是處理I/O。所以它永遠不允許用戶鎖上程序。它要求用戶不斷的處理新事物,因此它很適用於網 絡編程。在你的伺服器上要與很多人打交道,你必須處理連結。Node鼓勵人們用非阻塞的模式。由於這個特性,你會發現Node在開發伺服器上比傳統編程語 言更加方便。
  • 初學編程為什麼要選擇Java語言
    Java語言的實用性是非常好的,Java是一種非常簡單的程式語言,是新一代語言的代表,在使用過程中具有很多的優點,並且應用範圍非常廣泛,能夠結合很多工具進行使用。很多初學者在開始學習程式語言的時候都會選擇Java語言,選擇Java語言的原因是什麼呢?下面小編大家具體介紹。
  • 編程也能好玩:Swift Playgrounds上手評測
    你控制這個「遊戲」的方式不是按鍵或掃動,而是輸入代碼。你可以全程使用鍵盤來操作,但蘋果針對觸屏上的編程體驗做了許多優化,讓你省去不少力氣。「這是一個專為觸控設計的環境,」蘋果的工具及技術產品營銷部門總監說。「你真正去觸摸代碼,你真正與它們互動。當你要為實現循環使用 a 的時候,你可以在代碼內拖拽這個循環。你擁有一個獨特的 iPad 編程體驗。」
  • 想學新的程式語言?考慮下 Go 吧!
    例如fmt包就是個非常高效的字符串處理工具:「fmt實現了I/O的格式化,提供了類似於C語言的printf和scanf的函數。格式的『動詞』的概念是從C語言繼承的,但要簡單得多。」fmt就是一個從流行的成功預言(如C語言)吸取並改進的例子。
  • 自動化程式語言的未來
    不過,問題是:與其它程式語言相比,梯形圖邏輯能在多大程度上滿足當前和未來複雜的自動化需求?答案可能比繼電器和線圈要複雜的多。梯形圖邏輯的起源自動化的出現要早於PLC,那時使用繼電器網絡來充當應用的「大腦」。沒有編程人員的角色:只有工程師負責設計電路、電工負責組裝。
  • 2020年,頂尖程式設計師最應該掌握的7種程式語言
    選自知乎用戶:https://www.zhihu.com/question/284549387/answer/451018336儘管在剛開始開發 AI 時,有很多程式語言都可以滿足你的需求,但沒有一種程式語言是可以一站式解決 AI 編程的問題,因為在每一個項目中,不同的目標需要特定的方法。
  • 開發語言這種事,中國人還是可以開發出來的,不過是有點難誒
    wenyan-lang對於這麼語言,開發者當然最想看的是語法,那麼,話不多說,直接來看語法吧:定義變量定義函數看到這裡,你會否覺得自己已經可以用這個語言來寫程序了呢?下面來看一個簡單的案例,實現一個列印的Hello word!源碼如下:吾有一數。
  • 2020 年七大 AI 程式語言大盤點
    隨著近年來的發展,人工智慧促進企業的發展,這該歸功於底層程式語言核心的改進。隨著人工智慧的蓬勃發展和程式語言的持續改進,對高效、熟練的程式設計師和工程師的需求激增。雖然有很多程式語言可以讓你在人工智慧上開發領域輕鬆起步,但是沒有一種程式語言可以成為人工智慧編程的「一站式」解決方案,因為每種程式語言都有自己的獨特之處。目的不同,對語言的要求也會不同。
  • Julia:高性能 GPU 計算的程式語言
    【IT168 評論】Julia是一種用於數學計算的高級程式語言,它不僅與Python一樣易於使用,而且還與C一樣快。Julia是出於性能考慮而創建的,它的語法與其他程式語言相似,但是卻擁有和編譯型語言相媲美的性能。  如今,在多核CPU和大型並行計算系統的編程中,Julia已經非常受歡迎了。
  • 一派胡言的蓬佩奧還能蹦躂到幾時?
    日前,美國國務卿蓬佩奧在其來日無多的「最後瘋狂」中又顛倒黑白、一派胡言,竟然宣稱「臺灣一直不是中國的一部分」。前不久蓬佩奧訪問亞洲多國,一路不斷散播反華言論,絞盡腦汁、使用各種手段拉人下水,妄圖組織「反華大合唱」。事實證明,散布謊言沒有市場,單邊主義不得人心,蓬佩奧縱然使出渾身解數,最終還是落得個自言自語、無人搭理的窘境。不過,滿腦子冷戰思維的蓬佩奧看樣子是一根筋走到底,吃了秤砣鐵了心,執意在當反華「急先鋒」這條絕路上走到黑。
  • vb程式語言是做什麼用的_VB程式語言有哪些
    什麼是程式語言   程式語言(programming language),是用來定義電腦程式的形式語言。它是一種被標準化的交流技巧,用來向計算機發出指令。一種計算機語言讓程式設計師能夠準確地定義計算機所需要使用的數據,並精確地定義在不同情況下所應當採取的行動。
  • Python和C語言的語法有什麼不同?
    隨著經濟發發展,網際網路精英的缺乏越來越嚴重了,尤其是編程工程師,市場缺乏率極高,所有對於準備即將學習編程朋友,是一個非常的好時機 python與C的區別如下: 1、語言類型:Python是一種基於解釋器的語言,會逐行讀取代碼,將Python編譯為字節碼,由大型C程序解釋;C是一種編譯語言,完整的原始碼將直接編譯為機器代碼,由CPU直接執行。
  • Zig 0.7.1 發布,想要替換 C 的程式語言
    Zig 是一門通用程式語言,專為穩定性、可維護性和性能而設計,追求替代 C 語言在系統編程上的最佳地位。Zig 具有以下值得關注的特性: 手動管理內存 與 C 語言競爭而非依賴它,Zig 標準庫不依賴於 libc 輕量而簡單,專注於調試應用而不是調試程式語言的知識 新的錯誤處理方法,與編寫良好的 C 語言錯誤處理類似,但減少了很多冗餘 調試模式下優化了快速編譯時間,並在不確定行為發生時使用堆棧跟蹤崩潰 ReleaseFast 模式和 ReleaseSafe 模式 泛型數據結構和函數 通過協程實現並發
  • 蘋果iPhone6程式語言Swift發布:全面優於Objective-C語言
    蘋果iPhone6程式語言Swift發布:全面優於Objective-C語言網易6月3日消息 Swift語言一經發布就佔據了各大開發者的眼球,早上刷微信朋友圈,發現漫天遍地都是招聘Swift語言的程式設計師,看來蘋果iPhone6
  • 第一篇:C語言編程基礎語法
    本專欄系列分六篇,總結了C語言基礎知識的核心要點。教學視頻已上線,讀者可根據自身情況有選擇性地學習。01編程基礎C語言——貝爾實驗室、Dennis Ritchie屬於高級語言,更接近人類語言邏輯,需要編譯器編譯,執行依賴運行環境;但容易學習。其特點:模塊化編程程序設計,層次清晰;語句簡潔,提出程序庫概念;功能強大,系統、應用軟體均可開發;移植性好,適合不同的作業系統。除此之外,C語言還有豐富的運算符、數據結構等,程序設計自由度大,可以對硬體進行操作。
  • 你真的了解 TIOBE 程式語言排行榜嗎?
    接著,我們來看下 TIOBE 官方對這個程式語言排行榜的解讀:Object-C(下面簡稱 OC)和Perl語言從2017到2018跌落超過3個名次,OC名次跌落的原因很簡單,蘋果公司幾年前就開始拋棄OC,取而代之的是swift。