内容

名称

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

智能匹配

智能匹配现在被视为失败的实验,并在 Perl 5.37.10 中被标记为已弃用。这包括 whengiven 关键字,以及智能匹配运算符 ~~。该功能将在 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 实用程序函数

先前从 Pod::Html 导入的三个实用函数的定义和文档已在 Perl 5.36 中移至新包 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 之前,将 $* 设置为真值会全局启用字符串内的多行匹配。这个来自过去的遗物在 5.10 中失去了其特殊含义。在 Perl 5.30 中,使用此变量将成为致命错误,从而释放该变量以供将来使用特殊含义。

要启用多行匹配,应该使用 /m 正则表达式修饰符(可能与 /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++ } }

在 Perl 5.10 中,在错误条件下使用 my() 已被弃用,并在 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() 将文件句柄和目录句柄都与同一个符号(全局变量或标量)关联。这种用法可能会造成混淆,它在 Perl 5.10 中已被弃用。

从 Perl 5.28 开始,使用相同的符号来 open() 文件句柄和目录句柄将抛出致命错误。

您应该使用两个不同的符号。

${^ENCODING} 不再受支持。

特殊变量 ${^ENCODING} 用于实现 encoding 编译指示。在 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

Pod::Html 中的 --libpods

从 Perl 5.18 开始,选项 --libpods 已被弃用,使用此选项除了产生警告之外不会做任何事情。

从 Perl 5.26 开始,不再识别 --libpods 选项。

实用程序 c2phpstruct

这些旧的 perl3 时代实用程序长期以来已被弃用,取而代之的是 h2xs。从 Perl 5.26 开始,它们已被删除。

除了在程序退出期间捕获 $SIG {__DIE__}

即使在 eval() 内部也会调用 $SIG{__DIE__} 钩子。它本来不打算这样,但实现中的一个故障使这成为可能。这曾经被弃用,因为它允许在远处进行奇怪的操作,例如在 $@ 中重写挂起的异常。纠正此问题的计划已被取消,因为用户发现重写挂起的异常实际上是一个有用的功能,而不是一个错误。

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 同样适用。

另请参阅

警告诊断