Perl 5.36.0 帶來的新機能

作者:   發佈於:   #perl

在 2022 年 5 月釋出的 Perl 5.36.0 版中有不少舊的機能被徹底移除,但也多了不少新的機能。其中幾項令我注目的有:

subroutine signature

subroutine signature 在各語言中的意義都略有不同,但粗略地來說就是讓函式的參數列表成爲函式名稱的一部分。不過在 Perl 5.36.0 中尚沒有這麼先進,僅是把 @_ 這個代表參數列表的變數給藏了起來而已:

5.36.0 前的寫法:得多寫一行把 @_ 中各參數內容給拷貝出來:

sub foo {
    my ($p, $q) = @_;
    ...
}

自 5.36.0 起,可改寫成如下。把參數直接列在函式名後面。在語法上,省去了使用 @_ 的一步。

sub foo ($p, $q) {
    ...
}

這個語法自 5.20 版開始就被加入實驗組,幾番修改,現在總算是正式成爲核心語法的一部分了。

與此同時,如果在帶了參數列表的函式本文內又使用了 @_,就會讓 perl 發出警告。例如:

use v5.36;

sub plus ($p, $q) {
    return $p + $_[1];
}

say plus(10, 1);

輸出:

Use of @_ in array element with signatured subroutine is experimental at /tmp/x.pl line 4.
11

可看到 $_[1] 還是等於 $q,也還是可以用。但在執行時則會有一行警告訊息跑出來。

此外,還有個附帶的好處:在函式呼叫處,如果參數的個數與宣告處的參數個數不同,則會產生執行時期的錯誤,並且就地停止。比方說我們故意丟三個參數給 plus

use v5.36;

sub plus ($p, $q) {
    return $p + $q;
}

say "begin";
say plus(10, 1, 42);
say "end";

輸出:

begin
Too many arguments for subroutine 'main::plus' (got 3; expected 2) at /tmp/x.pl line 8.

可看到這程式輸出只到 "begin" 爲止,沒有包含 plus 傳回值,也沒有包含 "end"

其實我覺得最好是讓它在編譯時期就中止,不過目前這樣也還算不錯。只是在重構程式時要確保沒有少改任何一處,以免到部署上線之後才發現錯誤連連。

true, false, is_bool 及 builtin

一直以來 Perl 語言中都沒有對應到 true 與 false 這兩個值,現在有了。在程式中明確寫下來的 truefalse,在函式呼叫傳值的過程中,都會被好好保留著。但,這兩個關鍵字尚不是直接就建在語言內,而是要自名爲 builtin 的這個個新核心模組引入。除了新關鍵字之外,所有測試用運算子都會回傳 truefalse,而要明確判別 true/false 與其他值,則必須用 is_bool

use v5.36;
use builtin qw( true false is_bool );

my $p = (1 == 1);
say is_bool( $p ) ? "bool" : "not bool"; #=> "bool"

除了滿足新世代的「寫作習慣」之外,有特定值來代表 true / false 的好處就是能在將各變數轉換成 JSON 時,能夠清楚區分出 1"1"true 的不同,。

一次抓出多個值的 for 迴圈

這次在 for 迴圈的語法上加入了一次抓出多個值的新規則。讓人可以利用這種特性,使陣列內容兩兩一組或三三一組,做出簡單的資料結構。簡單的範例如下:

use v5.36;

for my ($x, $y, $z) (1..11) {
    say "$x $y $z";
}

輸出:

for my (...) is experimental at /tmp/x.pl line 4.
1 2 3
4 5 6
7 8 9
Use of uninitialized value in concatenation (.) or string at /tmp/x.pl line 5.
10 11 

可看到,在串列長度與迭代變數的個數不正好是倍數關係時,於最後一輪中,就會有幾個變數變成 undef。這設計還算合理。

感想

這次的新版出現了很多變更,稍微試用之後都覺得各設計還算合理。但似乎也有人覺得新語法的加入,漸漸地讓 Perl 語言失去了一些一致性,各語句之間變得越來越不像。不過多數變更都還是放在實驗組中的,起目的就是在於讓大家試用,找出癥結與痛點,加以改善,或是整組丟掉。

新的 builtin 核心模組的出現似乎是個不錯的方向,可把一些常用的,或不得不用的函式內部化,如果能逐漸充實到使人無需利用 CPAN 模組就能完成大部分簡單任務,那其實會是個很好的結果。