內容

名稱

perldeprecation - 列出 Perl 已過時的功能

說明

本文件旨在記錄 Perl 中已過時的功能,以及已過時功能將在何種版本中消失,或者對於已移除的功能,則記錄其移除時間。

本文件將嘗試討論已過時功能有哪些可用的替代方案。

已過時的功能將按其將在其中移除的 Perl 版本進行分組。

非預定已過時的功能

Unicode 分隔符將成對

過去允許一些 Unicode 分隔符作為單一字元,但未來將成為平衡對的一部分。此已過時功能類別用於標記那些將從不成對變為成對的字元。

類別:「deprecated::delimiter_will_be_paired」

Inc 中的點

目前的作業目錄 "." 過去會自動包含在 @INC 中,但在 Perl 5.26 中,這項功能已基於安全性考量而移除。從那時起,當使用者使用 do EXPREXPR 不包含路徑,且檔案未在 @INC 中的任何目錄中找到,但位於 "." 中時,我們會產生警告。檔案不會載入,但會產生已過時警告。

類別:"deprecated::dot_in_inc"

Goto 塊狀結構

goto LABEL; 會在從外部跳入迴圈或其他塊狀結構的主體時產生已棄用的警告。例如

while (should_loop($x)) {
    LABEL:
        do_stuff();
}
goto LABEL;

會產生此行為已棄用的警告。一般來說,您應該避免執行此操作,維護您的程式碼的人員會感激您的克制。

類別:"deprecated::goto_construct"

Unicode 屬性名稱

在正規表示式模式中使用各種類型的 Unicode 屬性名稱時,會產生已棄用的警告。例如,代理字元會導致棄用警告。

類別:"deprecated::unicode_property_name"

Perl 5.42

Smartmatch

Smartmatch 現在被視為失敗的實驗,並在 Perl 5.37.10 中標記為已棄用。這包括 whengiven 關鍵字,以及 smartmatch 運算子 ~~。此功能將在 Perl 5.42.0 正式版本中完全移除。

類別:"deprecated::smartmatch"

使用 ' 作為全域名稱分隔符號。

Perl 允許使用 ' 取代 :: 來替換套件或全域變數名稱的部分,例如 A::BA'B 是等效的。

' 將不再被 Perl 5.42 識別為名稱分隔符號。

類別:"deprecated::apostrophe_as_package_separator"

Perl 5.40

use VERSION 降級到 v5.11 以下

一旦 Perl 看到了請求版本 v5.11 或以上的 use VERSION 宣告,後續請求較早版本的第二個宣告會印出已棄用警告。例如,

use v5.14;
say "We can use v5.14's features here";

use v5.10;        # This prints a warning

此行為將在 Perl 5.40 中移除;後續請求將變成編譯時期錯誤。

這是因為 use VERSIONuse strict 之間的互動關係預計會發生相關變更。如果您指定版本 >= 5.11,則會隱式啟用 strict。如果您請求版本 < 5.11,則 strict 將會停用,即使您先前已寫入 use strict。這並非 use VERSION 先前的行為,目前將獨立追蹤明確啟用的 strictness 旗標。

類別:"deprecated::version_downgrade"

Perl 5.38

Pod::Html 實用程式函式

在 Perl 5.36 中,先前可從 Pod::Html 匯入的三個公用程式函數的定義和文件移至新的套件 Pod::Html::Util。雖然它們在 Perl 5.36 中仍可從 Pod::Html 匯入,但從 Perl 5.38 開始,它們只能應要求從 Pod::Html::Util 匯入。

Perl 5.34

Perl 5.34 中沒有非建議使用或致命錯誤。

Perl 5.32

可能在其他地方修改的詞彙變數常數

您寫了類似以下內容

my $var;
$sub = sub () { $var };

但 $var 在其他地方被參照,且可能在評估 sub 表達式後被修改。它不是在其他地方明確修改($var = 3),就是傳遞給子常式或運算子,例如 printfmap,它們可能會或可能不會修改變數。

傳統上,Perl 會在那個時間點擷取變數的值,並將子常式轉換為符合內聯資格的常數。在變數可能在其他地方被修改的情況下,這會破壞封閉的行為,其中子常式擷取變數本身,而不是其值,因此變數的未來變更會反映在子常式的回傳值中。

如果您打算讓子常式符合內聯資格,請確保變數未在其他地方被參照,可能透過複製它

my $var2 = $var;
$sub = sub () { $var2 };

如果您確實希望此子常式成為封閉,反映其封閉變數的未來變更,請新增明確的 return

my $var;
$sub = sub () { return $var };

此用法已被棄用,且從 Perl 5.32 開始不再允許。

使用字元碼點超過 0xFF 的字串作為 vec 的引數

vec 將其字串引數視為位元序列。包含字元碼點超過 0xFF 的字串是沒有意義的。此用法在 Perl 5.28 中已被棄用,並在 Perl 5.32 中移除。

在字串位元運算子中使用字元碼點超過 0xFF

字串位元運算子 &|^~ 將其運算元視為位元組字串。因此,超過 0xFF 的值毫無意義。這些運算子的一些實例自 Perl 5.24 起已棄用,並在 5.28 中變成致命錯誤,但事實證明,在寬字元不影響最終結果的情況下,並未提出棄用通知,因此仍然合法。現在,所有出現的情況都是致命錯誤或會提出棄用警告,因此 5.32 中剩下的合法出現情況變成了致命錯誤。

以下是範例:

"" & "\x{100}"

由於左運算元較短,因此 & 運算中不會使用寬字元。這現在會擲回例外狀況。

hostname() 不接受任何引數

Sys::Hostname 模組中的函式 hostname() 一直有文件說明,呼叫時不帶任何引數。過去它並未強制執行這項規定,實際上已接受並忽略任何引數。結果,有些使用者錯誤地認為引數會產生一些有用的結果。為避免這些錯誤,函式正在變得嚴格。傳遞引數已在 Perl 5.28 中棄用,並在 Perl 5.32 中變成致命錯誤。

正規表示式中的未跳脫左大括號

要記住的簡單規則是,如果你想在正規表示式模式中比對一個字面 { 字元(U+007B LEFT CURLY BRACKET),請以某種方式跳脫它的每個字面實例。通常最簡單的方法是在其前面加上反斜線,例如 \{ 或將其括在方括號中([{])。如果模式分隔符號也是大括號,任何匹配的右大括號(})也應該跳脫,以避免混淆解析器,例如:

qr{abc\{def\}ghi}

強制字面 { 字元跳脫將使 Perl 語言能夠在未來的版本中以各種方式擴充。為避免不必要地中斷現有程式碼,在不太可能出現擴充與其將 { 用作字面的用法衝突的環境中,不會強制執行此限制。在可能會對其感到困惑的環境中,會提出非棄用警告,說明左大括號被視為字面。

{ 的字面使用在 Perl 5.20 中已不建議使用,而某些使用情況自此開始發出不建議使用的警告。這些情況在 Perl 5.26 中變為致命錯誤。由於疏忽,並非所有使用字面 { 的情況都會收到不建議使用的警告。有些情況在 Perl 5.26 中開始發出警告,並在 Perl 5.30 中變為致命錯誤。其他情況則在 Perl 5.28 中開始,並在 5.32 中變為致命錯誤。

在 XS 程式碼中,使用處理 UTF-8 的各種巨集。

以下巨集現在需要一個額外的參數,多於 Perl 5.32 之前的版本。每個巨集中最後一個參數是指向第一個參數提供的字串中的指標,輸入不會讀取其後的內容。這可防止潛在的讀取超出緩衝區的結尾。isALPHANUMERIC_utf8isASCII_utf8isBLANK_utf8isCNTRL_utf8isDIGIT_utf8isIDFIRST_utf8isPSXSPC_utf8isSPACE_utf8isVERTWS_utf8isWORDCHAR_utf8isXDIGIT_utf8isALPHANUMERIC_LC_utf8isALPHA_LC_utf8isASCII_LC_utf8isBLANK_LC_utf8isCNTRL_LC_utf8isDIGIT_LC_utf8isGRAPH_LC_utf8isIDCONT_LC_utf8isIDFIRST_LC_utf8isLOWER_LC_utf8isPRINT_LC_utf8isPSXSPC_LC_utf8isPUNCT_LC_utf8isSPACE_LC_utf8isUPPER_LC_utf8isWORDCHAR_LC_utf8isXDIGIT_LC_utf8toFOLD_utf8toLOWER_utf8toTITLE_utf8toUPPER_utf8

自 Perl 5.26 起,具有額外參數的此功能可透過使用對應於其中每個巨集的巨集來使用,其名稱是由將 _safe 附加到基本名稱而形成的。這些巨集的功能沒有變更。例如,isDIGIT_utf8_safe 對應於 isDIGIT_utf8,而現在兩者的行為都相同。所有巨集都記載於 perlapi 中的「字元大小寫變更」perlapi 中的「字元分類」

此變更原定於 5.30,但已延遲至 5.32。

File::Glob::glob() 已被移除

File::Glob 有個稱為 glob 的函式,它只會呼叫 bsd_glob

File::Glob::glob() 在 Perl 5.8 中已不建議使用。從 Perl 5.26 起發出不建議使用的訊息,此函式在 Perl 5.30 中變為致命錯誤,並在 Perl 5.32 中完全移除。

使用 File::Glob::glob() 的程式碼應改為呼叫 File::Glob::bsd_glob()

Perl 5.30

$* 不再受支援

在 Perl 5.10 之前,將 $* 設定為 true 值會在字串中啟用多行比對。這個過去的遺留物在 5.10 中失去了其特殊意義。在 Perl 5.30 中,使用這個變數會變成一個致命錯誤,讓這個變數可以保留給未來的特殊意義。

若要啟用多行比對,應使用 /m regexp 修改器(可能與 /s 結合使用)。這可以在每個比對的基礎上設定,或可以使用 use re '/m' 在每個詞彙範圍(包括整個檔案)中啟用。

$# 不再受支援

這個變數過去有一個特殊意義,可以用來控制數字列印時的格式。這個很少使用的功能在 Perl 5.10 中被移除。為了讓這個變數可以保留給未來的特殊意義,在 Perl 5.30 中,使用這個變數會變成一個致命錯誤。

若要指定數字列印時的格式,建議使用 printfsprintf

將非零值指定給 $[ 是致命的

這個變數(以及對應的 array_base 功能和 arybase 模組)允許變更陣列和字串索引操作的基底。

自 Perl 5.12 起,將此設定為非零值已被棄用,並從 Perl 5.30 起會擲出致命錯誤。

File::Glob::glob() 將會消失

File::Glob 有個稱為 glob 的函式,它只會呼叫 bsd_glob。但是,它的原型與 CORE::glob 的原型不同,因此不應使用 File::Glob::glob

File::Glob::glob() 在 Perl 5.8 中已被棄用。從 Perl 5.26 起會發出棄用訊息,而在 Perl 5.30 中,這已變成一個致命錯誤。

使用 File::Glob::glob() 的程式碼應改為呼叫 File::Glob::bsd_glob()

正規表示式中的未跳脫左大括號(適用於 5.30)

請參閱上方「正規表示式中未跳脫的左大括號」。

未限定的 dump()

在 Perl 5.8 中,使用 dump() 取代 CORE::dump() 已被棄用,且自 Perl 5.30 起,未限定的 dump() 不再可用。

請參閱 perlfunc 中的「dump」

在錯誤條件中使用 my()。

Perl 中有一個長期的錯誤,導致在宣告中包含錯誤條件時,詞彙變數在範圍結束時不會被清除。有些人利用這個錯誤來取得一種靜態變數。為了讓我們修復這個錯誤,人們不應依賴這種行為。

建議改用 state 變數來達到相同的效果

use 5.10.0;
sub count {state $counter; return ++ $counter}
say count ();    # Prints 1
say count ();    # Prints 2

state 變數是在 Perl 5.10 中引入的。

或者,您可以透過在函式外部的獨立區塊中宣告變數來達到類似的靜態效果,例如,

sub f { my $x if 0; return $x++ }

變成

{ my $x; sub f { return $x++ } }

在錯誤條件中使用 my() 已在 Perl 5.10 中被棄用,並在 Perl 5.30 中成為致命錯誤。

從/寫入 :utf8 句柄的位元組。

在具有 :utf8 層(明確或隱含,例如,使用 :encoding(UTF-16LE) 層)的句柄上,sysread()、recv()、syswrite() 和 send() 算子已棄用。

sysread() 和 recv() 目前僅使用串流的 :utf8 旗標,忽略實際的層。由於 sysread() 和 recv() 沒有進行 UTF-8 驗證,因此它們可能會建立編碼無效的純量。

類似地,syswrite() 和 send() 僅使用 :utf8 旗標,否則會忽略任何層。如果設定旗標,則兩者都會以 UTF-8 編碼寫入值,即使該層是其他編碼,例如上述範例。

理想情況下,所有這些算子都將完全忽略 :utf8 狀態,僅使用位元組,但這將導致在不通知的情況下中斷現有程式碼。為了避免這種情況,未來的 perl 版本將在對具有 :utf8 層的句柄呼叫任何 sysread()、recv()、syswrite() 或 send() 時擲回例外。

從 Perl 5.30 起,不再可以使用 sysread()、recv()、syswrite() 或 send() 從/寫入 :utf8 句柄的位元組。

使用未分配的碼點或非獨立字元作為分隔符號。

字元是語言母語人士眼中所看到的字元。在 Unicode(因此也是 Perl)中,字元實際上可能是幾個相鄰的字元,它們共同形成一個完整的字元。例如,可以有一個基礎字元,例如「R」,和一個重音符號,例如揚抑符號「^」,當顯示時它們看起來像一個單一字元,揚抑符號懸浮在「R」上方。

自 Perl 5.30 起,使用非獨立字元的界定符號會造成致命錯誤,目的是讓此語言能接受多個字元的字元作為界定符號。

此外,自 Perl 5.30 起,禁止使用未分配的碼位作為界定符號,但未來可能會被分配。否則,如果目前未分配的界定符號最後變成非獨立字元,現在可以執行的程式碼將無法編譯。由於 Unicode 永遠不會分配非字元碼位,也不會分配超過 Unicode 合法最大值的碼位,因此這些可以作為界定符號。

Perl 5.28

屬性 :locked:unique

屬性 :locked(在程式碼參照中)和 :unique(在陣列、雜湊和純量參照中)自 Perl 5.005 和 Perl 5.8.8 起就沒有作用了。自此之後,它們的使用已被棄用。

自 Perl 5.28 起,這些屬性會造成語法錯誤。由於這些屬性沒有任何作用,因此從程式碼中移除它們可以修正語法錯誤;而且移除它們不會影響程式碼的行為。

未加引號的 here-document 終止符

Perl 允許您使用未加引號的 here-document 終止符,讓 here-document 在第一個空白行結束。此做法已在 Perl 5.000 中被棄用;自 Perl 5.28 起,使用未加引號的 here-document 終止符會擲出致命錯誤。

如果您希望使用空白行作為 here-document 的終止符,建議您使用明確引用的形式。

print <<"";
  Print this line.

# Previous blank line ends the here-document.

將 $/ 設定為非正整數的參照

您將一個純量參照指定給 $/,而參照的項目不是正整數。在舊版的 Perl 中,這看起來與將其設定為 undef 相同,但實際上在內部運作不同,效率較差,而且運氣很差的話,可能會導致您的檔案被參照的字串化形式分割。

在 Perl 5.20.0 中,這已變更為完全與將 $/ 設定為 undef 相同,但會擲出此警告例外。

自 Perl 5.28 起,將 $/ 設定為非正整數的參照會擲出致命錯誤。

如果您希望讀取檔案,建議您將程式碼變更為將 $/ 明確設定為 undef

Unicode 碼點值限制。

Unicode 僅允許最高 0x10FFFF 的碼點,但 Perl 允許更大的碼點。在 Perl 5.28 之前,允許使用超過整數最大值 (IV_MAX) 的碼點。然而,這會在某些結構中中斷 perl 執行器,包括在某些情況下導致執行器當機。已知的問題區域在於 tr///、使用量詞的正規表示式模式比對、qX...X 中的引號分隔符 (其中 X 是大碼點的 chr()) 以及迴圈中的上限。

在 Perl 5.24 中已棄用超出範圍碼點的使用;從 Perl 5.28 開始,使用超過 IV_MAX 的碼點會擲出致命錯誤。

如果您的程式碼要在各種平台上執行,請記住上限取決於平台。在 64 位元字組大小上遠大於 32 位元字組大小。對於 32 位元整數,IV_MAX 等於 0x7FFFFFFF,對於 64 位元整數,IV_MAX 等於 0x7FFFFFFFFFFFFFFF

格式中使用無逗號變數清單。

允許在格式中使用變數清單,而不用逗號分隔。此用法已棄用很長一段時間,從 Perl 5.28 開始,這會擲出致命錯誤。

使用 \N{}

在 Perl 5.24 中已棄用在大括號之間沒有任何內容的 \N{},從 Perl 5.28 開始會擲出致命錯誤。

由於這樣的結構等於使用空字串,建議您移除此類 \N{} 結構。

使用相同符號開啟檔案句柄和目錄句柄

過去可以使用 open() 將檔案句柄和目錄句柄都關聯到同一個符號 (glob 或純量)。此慣例可能會造成混淆,且已在 Perl 5.10 中棄用。

從 Perl 5.28 開始,使用相同符號 open() 檔案句柄和目錄句柄會擲出致命錯誤。

您應該改用兩個不同的符號。

${^ENCODING} 不再支援。

特殊變數 ${^ENCODING} 用於實作 encoding pragma。在 Perl 5.22 中,將此變數設定為非 undef 已被棄用。在 Perl 5.25.3 中,此變數已完全棄用。

自 Perl 5.28 起,將此變數設定為非未定義值會擲出致命錯誤。

B::OP::terse

此方法僅呼叫 B::Concise::b_terse,已遭棄用,並在 Perl 5.28 中移除。請改用 B::Concise

不再允許使用繼承的 AUTOLOAD 來呼叫非方法 %s::%s()

作為一項(嗯哼)意外的功能,AUTOLOAD 子常式會視為方法(使用 @ISA 階層)進行查詢,即使要自動載入的子常式是以一般函數呼叫(例如 Foo::bar()),而非方法(例如 Foo->bar()$obj->bar())。

此錯誤在 Perl 5.004 中已遭棄用,並在 Perl 5.28 中已修正,僅對方法的 AUTOLOAD 使用方法查詢。

簡單的規則是:自動載入非方法時,繼承將無法運作。舊程式碼的簡單修正方式是:在任何依賴從名為 BaseClass 的基底類別繼承非方法的 AUTOLOAD 的模組中,於啟動時執行 *AUTOLOAD = \&BaseClass::AUTOLOAD

在目前寫法為 use AutoLoader; @ISA = qw(AutoLoader); 的程式碼中,您應從 @ISA 中移除 AutoLoader,並將 use AutoLoader; 變更為 use AutoLoader 'AUTOLOAD';

字串位元運算子中使用超過 0xFF 的碼點

字串位元運算子 &|^~ 將其運算元視為位元組字串。因此,超過 0xFF 的值是沒有意義的。在 Perl 5.24 中,使用這些運算子時使用此類碼點已遭棄用,並在 Perl 5.28 中會造成致命錯誤。

在 XS 程式碼中使用 to_utf8_case()

此函式已於 Perl 5.28 中移除;請改為呼叫適當的函式:toFOLD_utf8_safetoLOWER_utf8_safetoTITLE_utf8_safetoUPPER_utf8_safe

Perl 5.26

--libpodsPod::Html

自 Perl 5.18 以來,--libpods 選項已被棄用,使用此選項除了產生警告之外,不會執行任何其他操作。

自 Perl 5.26 起,不再辨識 --libpods 選項。

公用程式 c2phpstruct

這些舊的 perl3 時代公用程式很長一段時間以來已被棄用,並改用 h2xs。自 Perl 5.26 起,已將其移除。

在程式結束以外的時間捕捉 $SIG {__DIE__}

$SIG{__DIE__} 鉤子甚至在 eval() 內也會被呼叫。這原本不是預期的行為,但實作上的錯誤讓這成為可能。這曾被棄用,因為它允許在遠處執行奇怪的動作,例如改寫 $@ 中的待處理例外。修正此問題的計畫已被取消,因為使用者發現改寫待處理例外實際上是一個有用的功能,而不是錯誤。

Perl 從未針對此問題發出棄用警告;棄用僅限於文件政策。但自 Perl 5.26 起,已解除此棄用。

%s 中的 UTF-8 字串格式錯誤

此訊息表示 Perl 核心或 XS 程式碼中有錯誤。此類程式碼嘗試找出一個字元(據稱以 UTF-8 編碼儲存在內部)是否為特定類型,例如標點符號或數字。但該字元並未以合法的 UTF-8 編碼。%s 會替換成一個字串,知識淵博的人員可以使用該字串來判斷要檢查的類型為何。

在 Perl 5.18 中已棄用傳遞格式錯誤的字串,並在 Perl 5.26 中變成致命錯誤。

Perl 5.24

使用 *glob{FILEHANDLE}

在 Perl 5.8 中已棄用 *glob{FILEHANDLE} 的使用。目的是改用 *glob{IO}*glob{FILEHANDLE} 是其別名。

不過,此功能已在 Perl 5.24 中取消棄用。

呼叫 POSIX::%s() 已被棄用

POSIX 模組中的下列函式不再可用:isalnumisalphaiscntrlisdigitisgraphislowerisprintispunctisspaceisupperisxdigit。這些函式有錯誤,無法在 UTF-8 編碼字串上運作。請參閱 POSIX 中的條目以取得更多資訊。

這些函式已在 Perl 5.20 中標示為不建議使用,並在 Perl 5.24 中移除。

Perl 5.16

在沒有 * 的情況下,對控制代碼使用 %s 已不建議使用

過去可以在標量包含類型球體時,對標量使用 tietieduntie。這會導致其檔案控制代碼被繫結。當標量包含類型球體時,沒有辦法繫結標量本身,也沒有辦法解除繫結已指派類型球體的標量。

這在 Perl 5.14 中已不建議使用,而此錯誤已在 Perl 5.16 中修正。

因此,現在 tie $scalar 永遠會繫結標量,而不是它所包含的控制代碼。若要繫結控制代碼,請使用 tie *$scalar(加上明確的星號)。tied *$scalaruntie *$scalar 也適用相同的規則。

另請參閱

警告診斷