跳轉到內容

程式語言簡介/定義和示例

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

一些程式語言將函式視為 一等公民。換句話說,這些語言中的函式可以分配給變數,並且可以作為引數傳遞給其他函式並從其他函式中返回。這種能力為程式開發人員開闢了廣闊的可能性。在本節中,我們將探討其中的一些可能性。

定義和示例

[編輯 | 編輯原始碼]

我們將在本章中使用的一個基本概念是高階函式的概念,我們遞迴地定義如下

  • 不接收其他函式作為引數或返回函式的函式的階數為零。
  • 接收或返回階數為 n - 1 的函式的函式的階數為 n。

例如,以下在 SML 中實現的函式接收型別為 'a list 的多型列表,以及另一個型別為 'a -> 'b 的函式,並返回一個型別為 'b list 的新列表。我們透過將對映函式應用於輸入列表的每個元素來獲得此新列表

fun map _ nil = nil
 | map f (h::t) = f h :: map f t

我們的 map 函式非常可重用。我們可以將相同的演算法與許多不同型別的對映函式和輸入列表一起重用。以下是幾個示例

- map (fn x => x + 1) [1, 2, 3, 4];
val it = [2,3,4,5] : int list

- map op + [(1, 2), (3, 4)];
val it = [3,7] : int list

- map op ~ [1, 2, 3, 4];
val it = [~1,~2,~3,~4] : int list

- map (fn x => "String: " ^ Int.toString x) [1, 2, 3, 4];
val it = ["String: 1","String: 2","String: 3","String: 4"] : string list

在前面的示例中,map 是一個一階函式,因為它接收一個零階函式作為引數。高階函式在函式式語言中非常常見,例如 SML、HaskellocamlerlangF#。但是,即使是語義更命令式的語言,例如 C#PythonLua 也提供了此功能。事實上,幾乎所有現代程式語言都對高階函式提供了一些支援。下面我們看到我們的初始示例,即 map 函式,在 Python 中編碼

def map(f, l):
 return [f(x) for x in l]
 
print map(lambda x: x > 4, [2,3, 5, 7])

def inc(x): return x + 1
print map(inc, [2, 3, 5, 7])

在 C 中,透過將函式指標作為其他函式的引數傳遞,也可以使用高階函式。例如,以下程式碼實現了我們最初的 map 示例。但是,我們指出這種編碼風格在 C 中並不典型,這可能解釋了該程式的相對冗長。

#include <stdio.h>
#include <stdlib.h>
 
int* map (int* a, unsigned size, int (*f)(int)) {
 int i = 0;
 int* narray = (int*) malloc(size * sizeof(int));
 while (i < size) {
  narray[i] = (*f)(a[i]);
  i++;
 }
 return narray;
}
 
int inc(int x) {
 return x + 1;
}
 
int sqr(int x) {
 return x * x;
}
 
void printvec(int* a, unsigned size) {
 int i = 0;
 while (i < size) {
  printf("%8d", a[i++]);
  if (! (i % 10) ) {
   printf("\n");
  }
 }
 printf("\n");
}
 
int main(int argc, char** argv) {
 int* a = (int*) malloc((argc - 1) * sizeof(int));
 int* b;
 int* c;
 int i = 1;
 while(i < argc) {
  a[i++] = atoi(argv[i]);
 }
 printvec(a, argc - 1);
 b = map(a, argc - 1, inc);
 printvec(b, argc - 1);
 c = map(a, argc - 1, sqr);
 printvec(c, argc - 1);
}

閉包

華夏公益教科書