PHP's Higher-Order Functions

【Higher-Order Functions】某函數如果可以接受函數當作參數,或者以函數為傳出值,我們就稱這樣的函數為「較高次方函數」(Higher-Order Function)。較高次方函數讓程式可以變得相當有彈性,而且寫法比OOP更精簡許多。函數式語言有相當大的威力來自較高次方函數,特別是函數式語言的程式庫往往會有許多較高次方函數,可以幫助你進行資料處理(例如特殊排序法、資料對應、資料過濾)、事件處理。

Higher-Order Functions 是一種 Functional Programming 特有的東西

這種東西一開始看說真的會覺得有點複雜,有點難懂,尤其是由 OOP 的語言轉換過來

不過看一次不懂沒關係,就看兩次,兩次不懂就多看幾次,不然就過段時間回來再看看

隨著對語言的熟悉度提高了,就會對許多東西都認為是理所當然

說不定兩個月後,原本不懂的東西,就突然可以輕鬆理解了!

這次要介紹的是 Higher-Order Functions

Filter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ary = array(
'coffee' => 90,
'water' => 25,
'tea' => 40
);
// Higher-Order Functions
$new_ary = array_filter($ary, function($o){
return $o < 50;
});
// $new_ary = array('water' => 25, 'tea' => 40);
// ForEach
$new_ary = array();
foreach($ary as $k => $o) {
if ($o < 50) {
$new_ary[$k] = $o;
}
}
// $new_ary = array('water' => 25, 'tea' => 40);

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ary = array(
'coffee' => array(
'price' => 150,
'weight' => 300
),
'water' => array(
'price' => 20,
'weight' => 200
),
'tea' => array(
'price' => 40,
'weight' => 160
),
);
// Higher-Order Functions
$new_ary = array_map(function($o){
return $o['price'] / $o['weight'];
}, $ary);
// $new_ary = array('coffee' => 0.5, 'water' => 0.1, 'tea' => 0.25);
// ForEach
$new_ary = array();
foreach($ary as $k => $o) {
$new_ary[$k] = $o['pricec'] / $o['weight'];
}
// $new_ary = array('coffee' => 0.5, 'water' => 0.1, 'tea' => 0.25);

Reduce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ary = array(
'coffee' => array(
'price' => 150,
'weight' => 300
),
'water' => array(
'price' => 20,
'weight' => 200
),
'tea' => array(
'price' => 40,
'weight' => 160
),
);
// Higher-Order Functions
$sum = array_reduce(function($c, $o){
$c += $o['weight'];
return $c;
}, $ary);
// $sum= 660;
// ForEach
$sum = 0;
foreach($ary as $k => $o) {
$sum += $o['weight'];
}
// $sum= 660;

Sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ary = array(1,5,3,2,4);
// Higher-Order Functions
usort($ary, function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
});
// $ary = array(1,2,3,4,5)
// ForEach
$i = $j = 0, $cnt = count($ary), $tmp = 0;
for(; $i < $cnt - 1; $++) {
for($j = $i + 1; $i < $cnt; $++) {
if($ary[$i] < $ary[j]) {
$tmp = $ary[i];
$ary[i] = $ary[j];
$ary[j] = $tmp;
}
}
}
// $ary = array(1,2,3,4,5)

以上的程式碼 100% 未經過測試,有錯誤請見諒,並在下面留言,我會再修正!

不只是 PHP,JavaScript 或是其他任何的 Functional Programming 都有此功能,只是語法略有不同

在這邊先介紹 PHP 過幾天在介紹 JavaScript 的寫法 :D

2014-10-17 更新

Higher-Order Functions稱為「高階函式」似乎更為適合,在 PHP 與 JavaScript 當中皆用傳入 callback 處理,最後再回傳結果的方式,透過這種方式可以減少實體化(PHP 5.3+),如果是較舊版的 PHP 則需要先建立 funciton 的實體,在呼叫 Higher-Order Functions 時在傳入。