PHP 7.4 新特性之箭頭函式

ruby發表於2019-09-06

在 PHP 中,以往我們傳遞閉包函式引數的時候,往往需要寫很多重複性的程式碼。在 PHP 7.4 中,我們在閉包裡面如果只是返回一個簡單的表示式的時候,我們可以以一種更簡潔的方式來傳遞閉包引數了。

以往寫法

在以往的 PHP 版本中,我們使用匿名函式的方式可能會顯得非常冗長,即使裡面只是一個簡單的返回,或者一個簡單的表示式。

比如:

$students = [
    [
        'name' => 'Foo',
        'age' => 20,
    ],
    [
        'name' => 'Bar',
        'age' => 21,
    ],
];

$names = array_map(function ($student) {
    return $student['name'];
}, $students);

寫過 ES6 或者 Java8 的朋友應該對箭頭函式這種寫法比較熟悉,對比一下:

ES6

let names = students.map(student => student.name)

JAVA8 則類似下面的 map 那樣

students.stream()
        .map(student -> student.name)
        .collect(Collectors.toList())

相對比之下,php 就顯得有些囉嗦,如果閉包函式里面需要使用外部變數,則還需要把每一個外部變數寫到 use 裡面,那就會更加冗長。

箭頭函式 hello world

現在我們使用箭頭函式來重寫一下上面的 array_map 呼叫:

$names = array_map(fn ($student) => $student['name'], $students);
var_dump($names);

線上執行以上程式碼: php74-playground

怎麼樣?是不是簡潔又清晰,看起來特別舒服。 functionreturnuse 這些全都不用寫了。

同時,如果需要使用外部的變數,再也不需要使用 use 來引入那些外部變數了,在箭頭函式後面的表示式直接可以使用:

$y = 10;
$fn = fn ($x) => $x + $y;
var_dump($fn(20)); // 30

線上執行以上程式碼: php74-playground

舊的寫法:

$y = 10;
$fn = function ($x) use ($y) {
    return $x + $y;
};
var_dump($fn(20)); // 30

箭頭函式寫法

基本形式

fn (parameter_list) => expr

簡單說一下(但是很重要):

  • fn 是箭頭函式標識,原來的 function 關鍵字在箭頭函式里只需寫 fn
  • (parameter_list) 是箭頭函式的引數列表,fn 和 括號不能省略
  • expr 這個名字已經說明了一切,這裡我們只能寫一個表示式,不能寫多個語句,不接受語句塊。
  • expr 是一個表示式,同時也是這個箭頭函式的返回值,原來的 return 不用寫了

有人會說,為什麼還要寫 fn,直接 parameter => expr 不就好了嗎?

這是因為這種寫法已經用於 PHP 的關聯陣列裡面了,衝突了。

想了解為什麼的可以看 rfc/arrow_functions_v2

函式簽名

  • fn (array $x) => $x;,引數型別限定
  • fn (): int => $x;,返回值型別限定
  • fn ($x = 42) => $x;,引數預設值
  • fn (&$x) => $x;,引數引用傳遞
  • fn &($x) => $x;,返回值引用
  • fn ($x, ...$rest) => $rest;

總的來說:

引數傳遞、引數型別限定、返回值型別限定、引用引數傳遞、返回值引用等寫法和舊的寫法一致。

不一樣的是:

  • 沒有了 functionreturnuse 等關鍵字,也沒有了大括號

  • 需要注意的是:不支援大括號,不像 ES6

    • 錯誤寫法:fn (array $x) => {return $x;};

相容性問題

  • 從 PHP 7.4 起,因為引入了 fn 關鍵字作為箭頭函式的語法,因此,如果你的程式碼裡面有 fn 命名的函式,可能會有衝突。

總結

  • 基本語法 fn (parameter_list) => expr

  • PHP7.4 的箭頭函式只支援簡單的表示式(只能寫一個表示式),不能使用大括號把表示式括起來

想嚐鮮的可以在 php74-playground 嘗試一下!基於 PHP 7.4.0RC1 版本。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章