從陳述式到表達式

閱讀時間約 5 分鐘

對於程序式編程來說,程式是由一系列的指令組成,例如計算數值、印出訊息、修改變數、呼叫子程序、配置變數的記憶體空間等。定義函式是為了讓一些程序可以重複利用,因此稱為子程序,其中參數為子程序中特別的變數,讓我們能夠透過它們控制子程序的行為。函式的回傳值只是一種方便將結果帶回來的方法,但一般只能回傳一個值,因此早期的c++函式庫常需要預先配置記憶體,再透過參數傳給子程序,讓子程序能夠將結果帶出去。在程式裡面是透過「陳述式」(statement)描述程序應該怎麼執行,其中包含宣告變數、指定變數值、修改變數數值、呼叫子程序等。而為了簡化程式碼,一些計算指令也可以寫成「表達式」(expression),讓多個指令可以縮減成單一陳述式。表達式讓我們不必為每個計算指令的結果設定變數,而是讓表達式本身代表結果。而呼叫函式的指令也可以當作表達式來使用,讓我們可以將更複雜的操作組合起來。但並不是所有的函式都是藉由回傳值帶回結果,很多都是藉由傳入的參考傳回結果,這種函式難以串聯起來,因而仍需要寫成一步一步的陳述式。而且帶有副作用的函式也不適合寫成表達式,因為表達式的執行順序並不明顯,很容易造成奇怪的結果。


對於函數式編程來說,表達式才是描述程式運作的基礎。函數式編程一般只以回傳值帶回結果,如果要回傳多個值就用乘法類型包裝起來,如果要根據狀況回傳不同的值就用加法類型。因此在函數式編程中,大部分的函式都可以透過表達式很容易地串聯起來。函式通常不代表某個程序,它代表的是透過給定的參數計算並組成結果,而且很少會修改參數的值。更抽象地,它還建立了回傳值與參數之間的依賴關係,因此如果我們擔心一個表達式的值受到什麼影響,可以直接找它的參數來判斷。反之,需要寫成陳述式的指令往往會帶有副作用,它會產生隱藏的依賴關係,因此改變陳述式的順序會造成行為的改變。當我們需要共享計算結果時,或是表達式太長需要分段時,也會使用let陳述式定義變數。如果計算過程沒有副作用,這種陳述式可以很容易地重構,例如重新排序、改變變數作用範圍、或是取代此變數成它的定義。因此一個操作有無副作用是很重要的,它會影響我們對於表達式或陳述式的看法,並改變重構程式碼的能力。


對於像是Haskell的純函數式程式語言,變數不可能被修改,也沒有辦法透過呼叫函式執行某種操作,因此根本沒有陳述式的概念,let in並不是陳述式,而且它只能為一個變數綁定值,並不能額外產生其他副作用。通常使用let是為了共用參考,而不是為了執行某種運算。因為沒有副作用,所有的函式都只是通過給定資訊計算出結果,並不能修改變數的值。因為沒有副作用,純函數式程式語言的重構非常輕鬆,這可以讓我們更加專注於內凜的結構,而非實際的語義和目的。非流程控制的陳述式如印出資訊、修改變數等操作則可以用monad實現,Haskell針對monad有特殊的語法糖,使得它寫起來像是陳述式。因為我們必須利用monad才能實現帶有副作用的程序,因此副作用得以明確地與一般的計算分離開來。這種將有無副作用的程序明確分開來看的方法就是純函數式程式語言的特性,同樣的概念也可以帶回一般的程式語言,透過明確說明函式的副作用,可以避免因為未注意的特性產生意外的結果。


因為本來就沒有陳述式,純函數式編程根本沒有一般的跳出流程的方法。它沒有return,函式的身體本身只能是一個代表回傳值的表達式,因此early return的技巧在這裡不管用。如果限定於例外處理的early return,可以用Maybe/Either monad達到相同的效果。return是很特別的陳述式,在這個陳述式之後的程式碼是不會執行的,類似的陳述式是throw等例外處理的機制。另一種說法是它們具有never type,也就是一個永遠不可能回傳的類型。類似throw陳述式的東西在Haskell是throw函式,它會丟出例外並跳出當前的執行程序。這類的函式會回傳Void,代表永遠不可能求值成功。Void可以當作任何類型,畢竟永遠不可能建構這個類型的值,相反的,標榜可以回傳任意類型的函式事實上就是不可能回傳的函式,這是在純函數式程式語言中對於例外的表達方式。


一般的if else判斷式是陳述式,因此這種流程控制方法在Haskell並不存在。Haskell的if then else類似於三元表達式,它會根據狀況切換到其中一個表達式,它們必須都有相同回傳類型。Haskell的條件式流程控制是基於模式匹配,也就是根據加法資料類型的結構控制流程,因此它可以看成是由資料本身決定流程,而非由我們主動決定。例如函式either可以根據Either類型的數值選擇呼叫哪一個函式,這跟case of的作用是一樣的。事實上所有的模式匹配都能寫成這種形式,因此我們根本不需要流程控制的語法。甚至也不需要定義代數資料類型的機制,所有代數特性都可以由特定的函式完整描述,這稱為Scott encoding。這顯示了代數資料類型本身描述的不是資料結構,而是資料的行為,也就是流程的控制。乘法資料結構Tuple可以透過函式uncurry描述,它代表同步的流程;加法資料結構Either可以由either描述,它代表流程的分支;List可由fold描述,它代表迴圈的流程;遞迴的資料結構可由相應的catamorphism描述,它代表遞迴的流程。可以說流程控制在Haskell只是一種特殊的函式,case of/pattern match/if then else只是使用這種特殊函式的語法糖。

4會員
28內容數
這不是教你如何從物件導向到函數式編程的入門教程。我會深入探討物件導向與函數式編程的差異,並討論為什麼你應該使用函數式編程並徹底放棄物件導向。
留言0
查看全部
發表第一個留言支持創作者!
have bear的沙龍 的其他內容
函數式編程跟物件導向一個很大的差異在於對資料可變性(mutability)的態度,函數式編程不鼓勵修改原有的資料,有些語言甚至沒有修改的概念;而物件導向專注於狀態的改變,物件作為閉包就已經假設資料是可變的。這種對於可變性的態度注定物件導向比較容易得到關注,因為這個模型比較符合電腦底層的運作邏輯,而我
這個系列的文章主要專注於物件導向到函數式編程的差異與分析,並針對概念與機制上的不同進行比較。很多人說物件導向和函數式編程沒有哪個比較好的問題,只有哪個比較適合的問題,然而我並不這麼認為,我透過這一系列的文章從各個角度討論它們之間的優缺點就是為了闡述我的觀點。物件導向錯在沒有理論基礎,但它贏在熟悉性,
前一篇文章中所提的函數式的三個機制明確說明了它關注的規則與能力具體是什麼。然而這套對於函數式編程的定義主要基於特定的類型系統,作為一個編程範式來說過於狹隘(物件導向的定義也是這樣)。更廣義的,我認為函數式編程主要依循三個原則,它們可以應用於任何程式語言,就算沒有靜態類型系統的支援也可以。例如在不管類
前面談了那麽多函數式編程與物件導向的差異,但我們還沒定義函數式編程。就像物件導向,函數式編程沒有明確的定義,每個人對於什麼是函數式編程都有不同的看法。在這裡我會總結前面的討論,給出我對於函數式編程的觀點。 物件導向注重封裝與延展性,因此一般基於三個機制:繼承、多型、封裝,它們代表了物件導向所重
說到物件導向就必須提五個原則,統稱SOLID,它被認為是物件導向的重要概念。這五個原則並不只適用於物件導向,事實上它很像函數式編程的習慣。它的命名很奇怪且容易讓人混淆,所以我會用我自己的翻譯解釋。 Single Responsibility Principle 是「單一職責原則」,認為一個模組
讓我在這篇文章總結一下前面對物件導向設計的討論,我們討論了物件導向的四個特性:繼承、抽象、多型、封裝,分析了它們的問題,並跟函數式編程的思維做比較。我們引入了與之相對應的特性:泛型、特性系統、模組化,有些特性雖然跟那四個特性很像,但在一些細微的地方有不同的詮釋,使得整體思考方式很不一樣。 「繼
函數式編程跟物件導向一個很大的差異在於對資料可變性(mutability)的態度,函數式編程不鼓勵修改原有的資料,有些語言甚至沒有修改的概念;而物件導向專注於狀態的改變,物件作為閉包就已經假設資料是可變的。這種對於可變性的態度注定物件導向比較容易得到關注,因為這個模型比較符合電腦底層的運作邏輯,而我
這個系列的文章主要專注於物件導向到函數式編程的差異與分析,並針對概念與機制上的不同進行比較。很多人說物件導向和函數式編程沒有哪個比較好的問題,只有哪個比較適合的問題,然而我並不這麼認為,我透過這一系列的文章從各個角度討論它們之間的優缺點就是為了闡述我的觀點。物件導向錯在沒有理論基礎,但它贏在熟悉性,
前一篇文章中所提的函數式的三個機制明確說明了它關注的規則與能力具體是什麼。然而這套對於函數式編程的定義主要基於特定的類型系統,作為一個編程範式來說過於狹隘(物件導向的定義也是這樣)。更廣義的,我認為函數式編程主要依循三個原則,它們可以應用於任何程式語言,就算沒有靜態類型系統的支援也可以。例如在不管類
前面談了那麽多函數式編程與物件導向的差異,但我們還沒定義函數式編程。就像物件導向,函數式編程沒有明確的定義,每個人對於什麼是函數式編程都有不同的看法。在這裡我會總結前面的討論,給出我對於函數式編程的觀點。 物件導向注重封裝與延展性,因此一般基於三個機制:繼承、多型、封裝,它們代表了物件導向所重
說到物件導向就必須提五個原則,統稱SOLID,它被認為是物件導向的重要概念。這五個原則並不只適用於物件導向,事實上它很像函數式編程的習慣。它的命名很奇怪且容易讓人混淆,所以我會用我自己的翻譯解釋。 Single Responsibility Principle 是「單一職責原則」,認為一個模組
讓我在這篇文章總結一下前面對物件導向設計的討論,我們討論了物件導向的四個特性:繼承、抽象、多型、封裝,分析了它們的問題,並跟函數式編程的思維做比較。我們引入了與之相對應的特性:泛型、特性系統、模組化,有些特性雖然跟那四個特性很像,但在一些細微的地方有不同的詮釋,使得整體思考方式很不一樣。 「繼
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
一個良好的早晨是一天成功的開端,讓我們一同探索如何打造清爽的生活起始,讓孩子充滿活力迎接每一天的挑戰。 朝陽迎接: 鼓勵孩子在朝陽下起床,享受自然光的提神效果,調整生理時鐘。 晨間活動: 安排一些輕鬆的晨間活動,如瑜珈、伸展操,激發孩子活力。 輕爽早餐: 提供清爽、易消化的早餐選擇,確保孩
Thumbnail
回想一下,當時準備選讀科系的時候, 你是清楚知道自己喜愛所讀,還是因為父母期待建議所讀? 如果發現自己的工作生活似乎就是這樣了,碰上了撞牆期, 那麼你會繼續妥協還是會勇敢地發覺應該會有另外一種可能?
Thumbnail
(文:外琨塔Vaikuntha藝術生活中心 | 策展人  李青芬) 陳益村 Chen Yi Tsun,1968年生,台灣苗栗人。 談及繪畫,陳益村提到:畫,療癒了我;也完整了我。 在陳益村的作品中,可以看到許多的圓,對他來說。圓,是人生的宏觀與縮影;是源點也是源爆;是緣起也是緣滅,是創作的起始
Thumbnail
藝術家陳益村,以繪畫創作為主,創作的過程,經過多種不同打底的嘗試以及思考,將具象或者抽象的畫面表現於畫布上,接著以一個一個小圈圈精雕細琢,時而運用圓圈作為如同遮罩的隱喻、時而讓圓圈為主體呈現半抽象的構圖畫面,每個圈圈都代表著他自己,在畫圓圈的過程,就像修行一樣,重複著同樣一件事情,在繪畫的過程中,會
Thumbnail
格式塔心理學(Gestalt psychology),又稱作完形心理學。Gestalt是德文音譯,中文直譯為格式塔,意即為形式或者模式,精神內涵就是動態整體的概念。此學派興起於20世紀初的德國,在現代心理學流派之中是重要的心理視覺理論之一,由三位德國心理學家 馬科斯·韋特墨(Max Wertheim
Thumbnail
去年對岸一部現象級網劇《陳情令》,改編自網路BL小說 《魔道祖師》,選角太神(帥哥太多),雖然已經被改編成社會主義兄弟情,好多同事都不可自拔。 我也看了原版小說之後徹底中毒,也因為這部小說,讓我觀察到對岸創作市場不可思議的一面
Thumbnail
陳建仁副總統卸任能領多少錢?去中研院能領多少錢?到民間作研究能領多少錢?接上市公司的獨立董事又能領多少錢?討論這些問題是人性的悲哀,也是整體社會病態的表現。
老䕺陳年鐵觀音(珍藏品) 純台灣鐵觀音極品珍藏老茶。 老茶第一次沖(茶水須熱) 1.第一泡茶不用洗(因家族白存)很乾淨. 2.3分之1壸荼葉 3.沖入熱水後等5-10秒後再倒茶水勿太快。 性.不泠.不熱.不傷胃 功用.幫助消化.消除外食一些不好油脂.及增強排毒.幚助新陳代謝..另消除血脂消除疲勞.
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
一個良好的早晨是一天成功的開端,讓我們一同探索如何打造清爽的生活起始,讓孩子充滿活力迎接每一天的挑戰。 朝陽迎接: 鼓勵孩子在朝陽下起床,享受自然光的提神效果,調整生理時鐘。 晨間活動: 安排一些輕鬆的晨間活動,如瑜珈、伸展操,激發孩子活力。 輕爽早餐: 提供清爽、易消化的早餐選擇,確保孩
Thumbnail
回想一下,當時準備選讀科系的時候, 你是清楚知道自己喜愛所讀,還是因為父母期待建議所讀? 如果發現自己的工作生活似乎就是這樣了,碰上了撞牆期, 那麼你會繼續妥協還是會勇敢地發覺應該會有另外一種可能?
Thumbnail
(文:外琨塔Vaikuntha藝術生活中心 | 策展人  李青芬) 陳益村 Chen Yi Tsun,1968年生,台灣苗栗人。 談及繪畫,陳益村提到:畫,療癒了我;也完整了我。 在陳益村的作品中,可以看到許多的圓,對他來說。圓,是人生的宏觀與縮影;是源點也是源爆;是緣起也是緣滅,是創作的起始
Thumbnail
藝術家陳益村,以繪畫創作為主,創作的過程,經過多種不同打底的嘗試以及思考,將具象或者抽象的畫面表現於畫布上,接著以一個一個小圈圈精雕細琢,時而運用圓圈作為如同遮罩的隱喻、時而讓圓圈為主體呈現半抽象的構圖畫面,每個圈圈都代表著他自己,在畫圓圈的過程,就像修行一樣,重複著同樣一件事情,在繪畫的過程中,會
Thumbnail
格式塔心理學(Gestalt psychology),又稱作完形心理學。Gestalt是德文音譯,中文直譯為格式塔,意即為形式或者模式,精神內涵就是動態整體的概念。此學派興起於20世紀初的德國,在現代心理學流派之中是重要的心理視覺理論之一,由三位德國心理學家 馬科斯·韋特墨(Max Wertheim
Thumbnail
去年對岸一部現象級網劇《陳情令》,改編自網路BL小說 《魔道祖師》,選角太神(帥哥太多),雖然已經被改編成社會主義兄弟情,好多同事都不可自拔。 我也看了原版小說之後徹底中毒,也因為這部小說,讓我觀察到對岸創作市場不可思議的一面
Thumbnail
陳建仁副總統卸任能領多少錢?去中研院能領多少錢?到民間作研究能領多少錢?接上市公司的獨立董事又能領多少錢?討論這些問題是人性的悲哀,也是整體社會病態的表現。
老䕺陳年鐵觀音(珍藏品) 純台灣鐵觀音極品珍藏老茶。 老茶第一次沖(茶水須熱) 1.第一泡茶不用洗(因家族白存)很乾淨. 2.3分之1壸荼葉 3.沖入熱水後等5-10秒後再倒茶水勿太快。 性.不泠.不熱.不傷胃 功用.幫助消化.消除外食一些不好油脂.及增強排毒.幚助新陳代謝..另消除血脂消除疲勞.