跳轉到內容

函數語言程式設計基礎

來自華夏公益教科書,開放的書籍,開放的世界

PAPER 2 - ⇑ 函數語言程式設計基礎 ⇑

什麼是函數語言程式設計 函數語言程式設計基礎 →


函數語言程式設計是一種 宣告式 程式設計正規化,其中程式被編寫為數學函式,其執行順序並非完全由程式設計師定義。這些數學函式會生成一致的輸出,這些輸出完全依賴於輸入。函式可以由其他函式構建,也可以遞迴地呼叫自身。函數語言程式設計在幾個方面不同於 指令式程式設計正規化

函式的輸出取決於輸入,而不是程式的不斷變化的狀態,函數語言程式設計是無狀態的。例如,下面的 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 的值

函數語言程式設計,fudgeNumbers
只返回值,它不會更改
其作用域之外的任何內容

函數語言程式設計還避免使用在執行時發生變化的變數,資料結構被認為是 不可變的

Python 示例 Haskell 示例
a = 2
b = 5
c = a + b
a = 6
a = 2
b = 5
c = a + b
不是函數語言程式設計,因為它
在執行時更改 a 的值

函數語言程式設計,變數只宣告一次

函數語言程式設計正規化 - 計算是對避免副作用和在執行時更改變數的數學函式的求值


函數語言程式設計正規化的優勢包括

  • 支援將計算問題分解和抽象成函式,這些函式由其他函式組成,而其他函式又由其他函式組成,等等。
  • 更易於閱讀和理解程式碼。
  • 更易於除錯程式碼,因為每個函式都可以單獨測試,並且不依賴於機器的狀態。
  • 適合於執行並行和併發程式執行,允許函式式程式在多處理器系統上執行。

Lisp 是最早的函數語言程式設計語言之一,誕生於 1958 年。Lisp 的幾種方言仍在普遍使用,包括 Common LispScheme。其他函數語言程式設計語言包括 ErlangHaskell。雖然指令式程式設計語言比純函式式語言更常用,但可以使用許多現代語言進行函數語言程式設計。其他支援函數語言程式設計的語言包括 PythonC#F#JavaVisual Basic .NETJavaScript

Scheme 程式碼示例
 (defun factorial (n)
   (if (= n 0) 1
       (* n (factorial (- n 1)))))

首次使用 Haskell

[編輯 | 編輯原始碼]

本章中的大多數程式碼示例將使用 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
練習:函數語言程式設計基礎

什麼是函數語言程式設計語言?

答案

函數語言程式設計語言是一種程式碼沒有副作用、程式執行是無狀態的,並且函式的輸出僅取決於輸入的語言。

描述使用函數語言程式設計語言的兩個好處

答案

  • 更易於除錯
  • 更易於閱讀和理解
  • 可以在並行系統上執行


解釋為什麼這不能被認為是函數語言程式設計的示例?

...
def multiply (a):
   return a * b
...

答案

我們不知道 b 在執行時的值,因此 multiply 函式會根據計算機的狀態輸出不同的值。


華夏公益教科書