函數語言程式設計基礎
| 有關 A 級(及更高)函數語言程式設計的更深入概述,請檢視 Richard Pawson 的 計算機科學從金屬向上 |
| 此頁面上的資料最初是為 isaac 計算機科學 編寫的 |
函數語言程式設計是一種 宣告式 程式設計正規化,其中程式被編寫為數學函式,其執行順序並非完全由程式設計師定義。這些數學函式會生成一致的輸出,這些輸出完全依賴於輸入。函式可以由其他函式構建,也可以遞迴地呼叫自身。函數語言程式設計在幾個方面不同於 指令式程式設計正規化
函式的輸出僅取決於輸入,而不是程式的不斷變化的狀態,函數語言程式設計是無狀態的。例如,下面的 Python 程式兩次呼叫相同的函式 addNumbers,引數相同 2,2,但返回了不同的值,因為程式的狀態(此處透過變數 c 模擬)發生了變化。在函數語言程式設計語言中不會發生這種情況,因為無論何時使用相同的引數呼叫函式,都會生成相同的輸出。
| Python 示例 | Haskell 示例 |
|---|---|
def addNumbers (a, b):
return a + b + c
...
print(addNumbers(2,2)) # prints 8
...
print(addNumbers(2,2)) # prints 6
|
addNumbers a b c = a + b + c
...
addNumbers 2 2 2 --returns 6
...
addNumbers 2 2 2 --returns 6
|
不是函數語言程式設計,因為 addNumbers 使用全域性變數 c |
函數語言程式設計,addNumbers 返回的值僅取決於輸入 |
函數語言程式設計語言避免副作用。副作用是指函式修改其區域性環境之外的內容。在下面的示例中,函式 fudgeNumbers 在執行時會更改全域性變數 g。
| Python 示例 | Haskell 示例 |
|---|---|
g = 0
def fudgeNumbers (a, b):
global g
g = a + (2 * b)
return a * b
print(g) # prints 0
print(fudgeNumbers(2,2)) # prints 4
print(g) # prints 6
|
g = 0
fudgeNumbers a b = a + b
g --returns 0
fudgeNumbers 2 2 --returns 4
g --returns 0
|
不是函數語言程式設計,因為 fudgeNumbers 會更改執行時全域性變數 g 的值 |
函數語言程式設計, |
函數語言程式設計還避免使用在執行時發生變化的變數,資料結構被認為是 不可變的。
| Python 示例 | Haskell 示例 |
|---|---|
a = 2
b = 5
c = a + b
a = 6
|
a = 2
b = 5
c = a + b
|
| 不是函數語言程式設計,因為它 在執行時更改 a 的值 |
函數語言程式設計,變數只宣告一次 |
函數語言程式設計正規化的優勢包括
- 支援將計算問題分解和抽象成函式,這些函式由其他函式組成,而其他函式又由其他函式組成,等等。
- 更易於閱讀和理解程式碼。
- 更易於除錯程式碼,因為每個函式都可以單獨測試,並且不依賴於機器的狀態。
- 適合於執行並行和併發程式執行,允許函式式程式在多處理器系統上執行。
Lisp 是最早的函數語言程式設計語言之一,誕生於 1958 年。Lisp 的幾種方言仍在普遍使用,包括 Common Lisp 和 Scheme。其他函數語言程式設計語言包括 Erlang 和 Haskell。雖然指令式程式設計語言比純函式式語言更常用,但可以使用許多現代語言進行函數語言程式設計。其他支援函數語言程式設計的語言包括 Python、C#、F#、Java、Visual Basic .NET 和 JavaScript。
| Scheme 程式碼示例 |
|---|
(defun factorial (n)
(if (= n 0) 1
(* n (factorial (- n 1)))))
|
本章中的大多數程式碼示例將使用 Haskell。您可以在 Learn You a Haskell for Great Good! 上了解有關 Haskell 的更多資訊。要執行本章中顯示的示例,您可以下載開源的 Glasgow Haskell Compiler 或 GHC。大多數示例可以直接寫入 GHC 提供給您的命令列介面,如下所示,帶有 .> 符號。例如
.> putStrLn "Hello World!"
Hello World!
.> 4 ^ 7
16328
.> [1..8]
[1,2,3,4,5,6,7,8]
.> round 7.8
8
後面的示例可能需要您編寫多行程式,尤其是在您需要宣告自己的函式時,為此,您需要開啟文字編輯器並將您的 Haskell 檔案儲存為 .hs 副檔名。例如
| myFirstHaskell.hs |
|---|
myFactorial :: (Integral a) => a -> a
myFactorial 0 = 1
myFactorial n = n * factorial (n - 1)
|
然後,我們可以使用 :l(載入)命令將此載入到 GHC 中,後跟檔案位置和名稱。
.> :l myFirstHaskell.hs
[1 of 1] Compiling Main ( myFirstHaskell.hs, interpreted )
Ok, modules loaded: Main.
現在,我們可以從命令列使用已載入的函式 myFactorial
.> myFactorial 4
24
| 還有其他 Haskell 開發環境可用,包括 repl.it |
|
練習:函數語言程式設計基礎 什麼是函數語言程式設計語言? 答案 函數語言程式設計語言是一種程式碼沒有副作用、程式執行是無狀態的,並且函式的輸出僅取決於輸入的語言。 描述使用函數語言程式設計語言的兩個好處 答案
解釋為什麼這不能被認為是函數語言程式設計的示例? ...
def multiply (a):
return a * b
...
答案 我們不知道
|