内容

名称

perl5380delta - perl v5.38.0 的新增内容

说明

本文档描述了 5.36.0 版本和 5.38.0 版本之间的差异。

核心增强功能

新的 class 特性

现在提供了一种用于定义对象类的实验性新语法,其中每个实例的数据存储在表现得像词法单元的“字段”变量中。

use feature 'class';

class Point
{
    field $x;
    field $y;

    method zero { $x = $y = 0; }
}

这在 perlclass 中有更详细的描述。有关其实现的内部机制和其他相关详细信息的说明,请参阅 perlclassguts

这仍然是一项新的实验性特性,并且仍在开发中。它将在未来的版本中得到进一步的补充、完善和修改。由于它是实验性的,因此它会在 experimental::class 类别中产生警告。可以通过 no warnings 语句使这些警告静默。

use feature 'class';
no warnings 'experimental::class';

支持 Unicode 15.0

有关详细信息,请参阅 https://www.unicode.org/versions/Unicode15.0.0/

弃用警告现在有特定的子类别

所有弃用警告现在都有自己的特定弃用类别,可以单独禁用。你可以在 perldeprecationwarnings 中查看所有已弃用特性的列表。以下列表来自 warnings

+- deprecated ----+
|                 |
|                 +- deprecated::apostrophe_as_package_separator
|                 |
|                 +- deprecated::delimiter_will_be_paired
|                 |
|                 +- deprecated::dot_in_inc
|                 |
|                 +- deprecated::goto_construct
|                 |
|                 +- deprecated::smartmatch
|                 |
|                 +- deprecated::unicode_property_name
|                 |
|                 +- deprecated::version_downgrade

仍然可以通过以下方式在单个语句中禁用所有弃用警告

no warnings 'deprecated';

但现在可以进行更细粒度的控制。正如历史上一直发生的那样,这些警告会通过以下方式自动启用

use warnings;

%{^HOOK} API 引入

由于各种原因,为一些 perl 关键字创建子例程包装器可能很困难。任何具有未定义原型的关键字都无法用子例程包装,而 perl 允许包装的一些关键字在实践中包装起来非常棘手。例如,require 包装起来很棘手,虽然有可能,但这样做会更改堆栈深度,而导出标准方法假设它们将导出到堆栈中特定堆栈深度的包,除非非常小心地实现,否则包装器将更改导出函数的位置。这可能会非常难处理。

因此,我们引入了一个名为 %{^HOOK} 的新哈希,旨在促进此类情况。当一个关键字支持任何类型的特殊钩子时,该钩子将存在于这个新哈希中。此哈希中的钩子将以其被调用的函数命名,后跟两个下划线,然后是其执行的阶段,当前在关键字执行之前或之后。

在此初始版本中,我们支持两个钩子 require__beforerequire__after。提供这些钩子是为了简化在 require 语句之前和之后执行任务。

有关更多详细信息,请参阅 perlvar

PERL_RAND_SEED

添加了一个新环境变量 PERL_RAND_SEED,可用于使 perl 程序在不显式使用 srand() 或在没有参数的情况下使用 srand() 时可重复。请参阅 perlrun。此功能可以在编译时通过在构建过程中传递

-Accflags=-DNO_PERL_RAND_SEED

Configure 来禁用。

签名中定义或且逻辑或赋值默认表达式

现在可以使用 //=||= 运算符为子例程签名参数分配默认表达式,以在调用者提供未定义或 false 值(分别)时应用默认值,而不仅仅是在完全缺少参数时应用默认值。有关更多详细信息,请参阅 perlsub 中的文档。

@INC 钩子增强以及 $INC 和 INCDIR

@INC 钩子的内部结构已经过强化,可以处理各种边缘情况,并且在钩子在 require 操作期间修改 @INC 时不再会段错误或引发断言失败。作为此项工作的一部分,我们现在确保在 require 调用期间最多执行一次任何给定的钩子,并且任何重复的目录都不会触发额外的目录探测。

为了让开发人员能够更好地控制动态模块查找,现在支持一种新的钩子方法 INCDIR。支持此方法的对象可以注入到 @INC 数组中,当在模块搜索过程中遇到它时,它将被执行,就像执行 INC 钩子一样,并且其返回值用作要搜索模块的目录列表。返回一个空列表充当空操作。请注意,由于此钩子返回的任何引用都将被字符串化并用作字符串,因此您可能无法通过此 API 返回稍后要执行的钩子。

在 require 过程中调用 @INC 钩子(INCINCDIR)时,$INC 变量将被本地化为钩子来源的 @INC 索引值。如果钩子希望覆盖 @INC 中的“下一个”索引,它可以将 $INC 更新为比所需索引少 1(undef 等于 -1)。这允许 @INC 钩子完全重写 @INC 数组,并让 Perl 从 @INC 的开头重新开始其目录探测。

@INC 中不支持 INCINCDIR 方法的 Blessed CODE 引用将不再触发异常,而是会与未 Blessed 的 coderef 一样被处理,并执行为 INC 钩子。

现在在编译时检测到从 deferfinally 中禁止的控制流

禁止通过 returngoto 等控制流尝试离开 deferfinally 块。以前版本的 Perl 只能在运行时实际尝试时检测到这一点。

此版本的 Perl 为许多可以在静态中确定的情况添加了编译时检测。这意味着在以前版本的 Perl 上成功编译的代码现在可能被报告为编译时错误。这仅发生在实际执行代码时会出现错误的情况下;错误只是发生在更早的时候。

模式中的乐观 Eval

在模式中使用 (?{ ... })(??{ ... }) 会在该模式中全局禁用各种优化。这可能是程序员希望的,也可能不是。此版本添加了 (*{ ... }) 等效项。唯一的区别是它不会禁用正则表达式引擎中的任何优化,并且永远不会禁用。这可能会使其在某种意义上变得不稳定,因为它将来可能会被调用更多或更少次数,但是它的执行次数将真正匹配正则表达式引擎的功能。例如,当 (?{ ... }) 包含在模式中时,某些类型的优化会被禁用,因此在正常使用中为 O(N) 的模式会使用 (?{ ... }) 模式变为 O(N*N)。切换到 (*{ ... }) 意味着模式将保持为 O(N)。

REG_INF 已从 65,536 提升至 2,147,483,647

过去,许多正则表达式量词都限制为 U16_MAX,但现在限制为 I32_MAX,因此现在可以编写 /(?:word){1000000}/。请注意,这样做可能会导致正则表达式引擎运行时间更长并使用更多内存。

新 API 函数 optimize_optree 和 finalize_optree

有两个新的 API 函数用于操作 optree 片段,确保您可以调用 optree 生成过程中可能无法调用的必需部分(例如,在创建自定义 LOGOP 时)。要访问这些函数,您首先需要设置一个 #define 以选择使用这些函数。

#define PERL_USE_VOLATILE_API

这些函数与解释器的内部工作方式密切相关,如果其他内部更改需要,它们可能会随时被更改或删除。

现在允许在 deferfinally 块中使用某些 goto

Perl 版本 5.36.0 添加了 defer 块,并允许 finally 关键字也向 try/catch 语法添加类似的行为。这些块不允许在主体中使用任何 goto 表达式,因为它可能导致控制流跳出块。现在,如果 goto 表达式具有常量目标标签,并且该标签在块中找到,则允许使用一些 goto 表达式。

use feature 'defer';

defer {
  goto LABEL;
  print "This does not execute\n";
  LABEL: print "This does\n";
}

新正则表达式变量 ${^LAST_SUCCESSFUL_PATTERN}

这允许访问当前作用域中匹配的最后一个成功模式。正则表达式引擎的许多方面都引用“最后一个成功模式”。空模式会重复使用它,所有正则表达式魔术变量都与它相关。这允许访问其模式。以下代码

if (m/foo/ || m/bar/) {
    s//PQR/;
}

可以重写如下

if (m/foo/ || m/bar/) {
    s/${^LAST_SUCCESSFUL_PATTERN}/PQR/;
}

它将执行完全相同的事情。

区域设置类别 LC_NAME 现在在参与平台上受支持

在具有 GNU 扩展 LC_NAME 类别的平台上,你现在可以使用它作为 POSIX 中的“setlocale” 的类别参数来设置和查询其语言环境。

不兼容的更改

readline() 不再清除流错误和 eof 标志

readline(),也拼写为 <>,会在流上发生错误后清除句柄的错误和 eof 标志。

在几乎所有情况下,此清除不再进行,因此错误和 eof 标志现在正确反映了 readline() 之后的流状态。

由于不再清除错误标志,因此在流上调用 close() 可能会失败,并且如果流没有显式关闭,则流的隐式关闭可能会产生警告。

这导致了下游 CPAN 模块中两种主要类型的错误,并且这些错误也可能出现在你的代码中

在错误时继续清除错误和 eof 标志的唯一情况是在 miniperl 中从 glob() 的子进程中读取时。这允许它在 close() 时正确报告子进程的错误。在正常的 perl 开发过程中不太可能出现此问题。

[GH #20060]

INIT 块不再在 BEGIN 中的 exit() 之后运行

INIT 块将不再在 BEGIN 内执行的 exit() 之后运行。这意味着 -v 选项和 -c 选项的组合不再执行编译检查以及显示 perl 版本。-v 选项在 BEGIN 块内打印版本信息后执行 exit(0),而 -c 检查是通过使用 INIT 钩子实现的,导致 -v 选项优先。

[GH #1537] [GH #20181]

语法错误不再产生“幻影错误消息”

通常,perl 会在遇到编译错误后继续解析源代码。在许多情况下,这很有用,例如,对于拼写错误的变量名,显示尽可能多的错误示例很有用。但在语法错误的情况下,继续进行通常会产生奇怪的错误消息,甚至可能在编译过程中导致分段错误。在此版本中,编译器将在遇到的第一个语法错误处停止。这意味着任何期望看到我们过去生成的特定错误消息的代码都会中断。发出的错误将是我们过去生成的诊断之一,但在某些情况下,过去生成的某些消息将不再显示。

有关更多详细信息,请参见“对现有诊断的更改”

utf8::upgrade()

从本版本开始,如果输入字符串为 undef,它将保持为 undef。以前它会被更改为已定义的零长度字符串。

对“线程安全”区域设置的更改

Perl 5.28 在支持它们的系统上引入了“线程安全”区域设置,即现代 Windows 和支持 POSIX 2008 区域设置操作的系统。这些系统通过使用每个线程的区域设置来实现此目的,同时继续支持旧的全局区域设置操作,以用于不需要采取必要步骤来使用较新的每个线程操作的代码。

事实证明,一些 POSIX 2008 平台有或有过错误的实现,这迫使 perl 不使用它们。${^SAFE_LOCALES} 标量变量包含 0 或 1,以指示 perl 是否认为当前平台具有可工作的线程安全实现。一些实现已经修复,但 FreeBSD 和 Cygwin 被新发现的错误足够多,以至于 perl 从此版本开始不再使用线程安全操作。因此,${^SAFE_LOCALES} 现在对它们来说是 0。可以通过添加Configure 选项 -DNO_POSIX_2008_LOCALE 来配置旧版本的 perl 以避免这些错误的实现。

v5.38 修复了所有以前 perl 中导致区域设置不能完全线程安全的错误。完成的第一个线程导致主线程(名为 thread0)恢复到启动时有效的全局区域设置,丢弃线程之前设置的任何区域设置。如果任何其他线程通过在 XS 代码中调用 switch_to_global_locale() 切换到全局区域设置,则这些线程将共享全局区域设置,并且 thread0 将不是线程安全的。

弃用

使用 ' 作为包名称分隔符已弃用

自 5.28 以来,在双引号字符串中命名的变量中使用 ' 作为包分隔符会发出警告。现在它在字符串插值和非插值上下文中都已弃用,并且将在 Perl 5.42 中删除。

Switch 和 Smart Match 运算符

“switch”特性和 smartmatch 运算符 ~~ 在 v5.10 中引入。它们的行为在 v5.10.1 中发生了重大变化。当在 v5.18.0 中添加“实验”系统时,switch 和 smartmatch 被追溯声明为实验性的。多年来,修复或补充这些特性的建议不断出现和消失。

在 v5.38.0 中,我们宣布实验失败。一些未来的系统可能会在概念上取代 smartmatch,但它尚未设计或构建。

这些特性将在 v5.42.0 中从 perl 中完全删除。

性能增强

模块和 Pragmata

更新的模块和 Pragmata

文档

新文档

perlclass

描述新的class功能。

perlclassguts

描述新的class功能的内部结构。

对现有文档的更改

我们已尝试更新文档以反映此文档中列出的更改。如果您发现我们错过了任何更改,请在 https://github.com/Perl/perl5/issues 中打开一个问题。

此外,已进行以下选定更改

perlapi

perldeprecation

perlintern

perlexperiment

perlfunc

perlhacktips

perlop

perlvar

诊断

对诊断输出(包括警告和致命错误消息)进行了以下添加或更改。有关诊断消息的完整列表,请参阅 perldiag

新诊断

新错误

新警告

对现有诊断的更改

配置和编译

测试

已添加和更改测试以反映此版本中的其他添加和更改。此外,还进行了以下重大更改

平台支持

已弃用平台

Ultrix

已移除 DEC Ultrix 的支持代码。Ultrix 是各种 Digital Equipment Corporation 机器上的原生类 Unix 操作系统。其最终版本发布于 1995 年。

平台特定说明

DragonflyBSD

跳过测试以解决 setproctitle() 中的一个明显错误。 [GH #19894]

FreeBSD

FreeBSD 不再使用线程安全区域设置操作,以避免 FreeBSD 中的一个错误

uname -p 替换 archname 的第一部分 [GH #19791]

Solaris

避免 NetBSD/Solaris 中 regexec.c 和 regcomp.c 中的一些编译器和编译问题。

Synology

更新 Synology DSM 7 自述文件。

Windows

修复 vmem.h 中 gcc-12 所需的 win32 内存对齐。

如果无法将提供的 time_t 转换为 FILETIME,则 Win32 上的 utimes() 会向 stderr 打印一条消息。 [GH #19668]

在某些情况下,stat()lstat() 返回的时间戳未考虑夏令时。 [GH #20018] [GH #20061]

stat() 现在适用于 AF_UNIX 套接字文件。 [GH #20204]

readlink() 现在返回符号链接重新解析点的 PrintName,而不是 SubstituteName,这应该使其更好地匹配创建链接时使用的名称。 [GH #20271]

Windows 上的 lstat() 现在将链接目标的长度作为文件的大小返回,就像在 POSIX 系统上一样。 [GH #20476]

Windows 上的 symlink() 现在将目标中的任何 / 替换为 \,因为 Windows 在符号链接中不识别 /。反向转换不会由 readlink() 执行。 [GH #20506]

symlink() 将目标设为目录的绝对路径时,错误地创建为文件符号链接。 [GH #20533]

POSIX::dup2 不再创建损坏的套接字。 [GH #20920]

关闭繁忙的管道可能导致 Perl 挂起。 [GH #19963]

内部更改

选定的错误修复

致谢

Perl 5.38.0 代表了自 Perl 5.36.0 以来大约 12 个月的开发,并且包含来自 100 位作者的 1,500 个文件中大约 290,000 行的更改。

不包括自动生成的文件、文档和发布工具,大约有 190,000 行更改到 970 个 .pm、.t、.c 和 .h 文件。

由于活跃的用户和开发人员社区,Perl 继续在第四个十年蓬勃发展。已知以下人员为 Perl 5.38.0 的改进做出了贡献

Alex、Alexander Nikolov、Alex Davies、Andreas König、Andrew Fresh、Andrew Ruthven、Andy Lester、Aristotle Pagaltzis、Arne Johannessen、A. Sinan Unur、Bartosz Jarzyna、Bart Van Assche、Benjamin Smith、Bram、Branislav Zahradník、Brian Greenfield、Bruce Gray、Chad Granum、Chris 'BinGOs' Williams、chromatic、Clemens Wasser、Craig A. Berry、Dagfinn Ilmari Mannsåker、Dan Book、danielnachun、Dan Jacobson、Dan Kogai、David Cantrell、David Golden、David Mitchell、E. Choroba、Ed J、Ed Sabol、Elvin Aslanov、Eric Herman、Felipe Gasper、Ferenc Erki、Firas Khalil Khana、Florian Weimer、Graham Knop、Håkon Hægland、Harald Jörg、H.Merijn Brand、Hugo van der Sanden、James E Keenan、James Raspass、jkahrman、Joe McMahon、Johan Vromans、Jonathan Stowe、Jon Gentle、Karen Etheridge、Karl Williamson、Kenichi Ishigaki、Kenneth Ölwing、Kurt Fitzner、Leon Timmermans、Li Linjie、Loren Merritt、Lukas Mai、Marcel Telka、Mark Jason Dominus、Mark Shelor、Matthew Horsfall、Matthew O. Persico、Mattia Barbon、Max Maischein、Mohammad S Anwar、Nathan Mills、Neil Bowers、Nicholas Clark、Nicolas Mendoza、Nicolas R、Paul Evans、Paul Marquess、Peter John Acklam、Peter Levine、Philippe Bruhat (BooK)、Reini Urban、Renee Baecker、Ricardo Signes、Richard Leach、Russ Allbery、Scott Baker、Sevan Janiyan、Sidney Markowitz、Sisyphus、Steve Hay、TAKAI Kousuke、Todd Rinaldo、Tomasz Konojacki、Tom Stellard、Tony Cook、Tsuyoshi Watanabe、Unicode Consortium、vsfos、Yves Orton、Zakariyya Mughal、Zefram、小鸡。

以上列表几乎肯定不完整,因为它是从版本控制历史中自动生成的。特别是,它不包括向 Perl bug 跟踪器报告问题的(非常感谢的)贡献者的姓名。

此版本中包含的许多更改源自 Perl 核心包含的 CPAN 模块。我们感谢整个 CPAN 社区帮助 Perl 蓬勃发展。

要获得 Perl 所有历史贡献者的更完整列表,请参阅 Perl 源代码发行版中的 AUTHORS 文件。

报告错误

如果您发现您认为是错误的内容,您可以在 https://github.com/Perl/perl5/issues 处查看 perl 错误数据库。Perl 主页 https://www.perl5.cn/ 上也可能有相关信息。

如果您认为自己有一个未报告的错误,请在 https://github.com/Perl/perl5/issues 处打开一个问题。务必将您的错误精简为一个微小但足够的测试用例。

如果您报告的错误具有安全影响,不适合发送到公共问题跟踪器,请参阅 perlsec 中的 “perlsec 中的安全漏洞联系信息”,了解如何报告该问题的详细信息。

致谢

如果您希望感谢 Perl 5 Porters 在 Perl 5 中所做的工作,您可以通过运行 perlthanks 程序来实现

perlthanks

这会向 Perl 5 Porters 列表发送一封电子邮件,表达您的谢意。

另请参阅

Changes 文件,解释如何查看已更改内容的详尽详细信息。

INSTALL 文件,解释如何构建 Perl。

README 文件,了解常规内容。

ArtisticCopying 文件,了解版权信息。