描述§
这份文档试图列出 Perl 特殊变量及其在 Raku 中的等效项,并说明它们之间必要的差异。
注意§
这份文档旨在帮助读者从 Perl 的特殊变量过渡到 Raku 中的等效项。有关 Raku 特殊变量的完整文档,请参阅每个变量的 Raku 文档。
特殊变量§
通用变量§
$ARG, $_§
值得庆幸的是,$_
在 Raku 中仍然是通用默认变量,就像在 Perl 中一样。Raku 中的主要区别在于你现在可以对它调用方法。例如,Perl 中的 say $_
在 Raku 中可以写成 $_.say
。此外,由于它是默认变量,你甚至不需要使用变量名。前面的例子也可以通过使用 .say
来实现。
@ARG, @_§
由于 Raku 现在有了函数签名,你的参数可以放在那里,而不是依赖 @_
来传递它们。实际上,如果你使用函数签名,使用 @_
会报错,因为它不能覆盖现有的签名。
但是,如果你没有使用函数签名,@_
将包含你传递给函数的参数,就像在 Perl 中一样。同样,与 $_
一样,你也可以对它调用方法。与 $_
不同的是,你不能假设 @_
是这些方法操作的默认变量(例如,@_.shift
可以工作,.shift
则不行)。
$LIST_SEPARATOR, $"§
目前,Raku 中没有列表分隔符变量的等效项。设计文档 S28 中说没有,所以你可能不要抱太大希望。
$PROCESS_ID, $PID, $$§
$$
在 Raku 中被 $*PID
替换。
$PROGRAM_NAME, $0§
你可以在 Raku 中通过 $*PROGRAM-NAME
访问程序名称。
注意:Raku 中的 $0
是保存正则表达式匹配中第一个捕获值的变量(即捕获变量现在从 $0
开始,而不是 $1
)。
$REAL_GROUP_ID, $GID, $(§
在 Raku 中,组信息由 $*GROUP
处理,它包含一个 IntStr
类型的对象,因此可以在字符串或数字上下文中使用。因此,组 ID 通过 +$*GROUP
获取,组名通过 ~$*GROUP
获取。
$EFFECTIVE_GROUP_ID, $EGID, $)§
有效组 ID 似乎目前没有在 Raku 中提供。
$REAL_USER_ID, $UID, $<§
在 Raku 中,用户信息由 $*USER
处理,它保存一个类型为 IntStr
的对象,因此可以在字符串或数字上下文中使用(这类似于组信息如何由 $*GROUP
对象处理)。因此,用户 ID 通过 +$*USER
获取,而用户名通过 ~$*USER
获取。
$EFFECTIVE_USER_ID, $EUID, $>§
Raku 不提供有效用户 ID。
$SUBSCRIPT_SEPARATOR, $SUBSEP, $;§
Raku 中不包含下标分隔符变量。坦率地说,如果你的 Perl 代码正在使用它,它几乎肯定非常非常旧了。
$a, $b§
$a
和 $b
在 Raku 中没有特殊含义。sort()
不对它们进行任何特殊处理。它们只是普通的旧变量。
此功能已通过具有占位符参数的块扩展,这些块更加通用。占位符变量使用 ^
twigil 创建(例如 $^z
)。它们可以在没有显式参数列表的裸块或子例程中使用。块的参数按其 Unicode 顺序分配给占位符变量。也就是说,即使变量在块中按 ($^q, $^z, $^a)
的顺序出现,它们也会按 ($^a, $^q, $^z)
的顺序分配。因此
sort , 1, 5, 6, 4, 2, 3;# OUTPUT: «(1 2 3 4 5 6)»sort , 1, 5, 6, 4, 2, 3;# OUTPUT: «(6 5 4 3 2 1)»for 1..9# OUTPUT: «312»
有关占位符变量的更多信息,请参阅 此页面
%ENV§
在 Raku 中,%ENV 已被 %*ENV 取代。请注意,此哈希的键在 Perl 和 Raku 之间可能不完全相同。例如,OLDPWD
在 Raku 的 %ENV 中缺失。
$OLD_PERL_VERSION, $]§
Raku 的运行版本由 $*RAKU
特殊变量保存,该变量是一个对象。运行版本通过 $*RAKU.version
获取,它返回类似于 v6.d
的内容;Raku 解释器的完整字符串化版本通过 $*RAKU.gist
获取,它返回类似于 Raku (6.d)
的内容。
$SYSTEM_FD_MAX, $^F§
在 Raku 中不再存在。
@F§
[需要进一步研究] 此时有点令人困惑。设计文档 S28 指出 Perl 中的 @F
在 Raku 中被 @_
取代,但目前尚不清楚它是如何工作的。另一方面,这目前有点无关紧要,因为 Perl 到 Raku 翻译文档表明 -a
和 -F
命令行开关尚未在 rakudo 中实现。
@INC§
在 Raku 中不再存在。请使用“use lib”来操作要搜索的模块存储库。最接近 @INC 的东西实际上是 $*REPO。但这与 @INC 的工作方式完全不同,主要是因为 Raku 的预编译功能。
# Print out a list of compunit repositories.say for .repo-chain;
%INC§
在 Raku 中不再存在。因为每个存储库负责记住哪些模块已被加载。你可以获取所有已加载模块(编译单元)的列表,如下所示
use Test;use MyModule;say flat .repo-chain.map(*.loaded); #-> (MyModule Test)
$INPLACE_EDIT, $^I§
S28 建议 $*INPLACE_EDIT,但它尚不存在。
$^M§
S28 建议 $*EMERGENCY_MEMORY,但它尚不存在。
$OSNAME, $^O§
这有点不清楚。它可能取决于你对“操作系统名称”的理解,因为设计文档 S28 有三个不同的建议,它们都给出了不同的答案。
目前有三个主要对象包含有关“运行环境”的信息。
$*KERNEL
提供有关正在运行的操作系统内核的信息;$*DISTRO
提供有关操作系统发行版的信息;$*VM
提供有关 Raku 正在运行的后端机器的信息。
以上所有对象都具有共同的方法
version
提供该组件的版本号;name
提供该组件的助记符名称;auth
提供该组件的已知作者。
作为一个简短的示例,以下代码片段打印了有关所有上述组件的信息
for , , -># Kernel# version 4.10.0.42.generic named linux by unknown# Distro# version 17.04.Zesty.Zapus named ubuntu by https://www.ubuntu.com/# VM# version 2017.11 named moar by The MoarVM Team
以上所有对象上的 Cool.Str
方法 会生成信息的简短版本,目前是 name
。
所有对象都有其他方法,这些方法在尝试识别确切的运行实例时可能很有用,有关更多信息,请使用 .^methods
来内省所有上述对象。
%SIG§
没有等效的变量。要让您的代码在接收到信号时执行,您可以调用 signal 子例程,它会返回一个可以被抽取的 Supply
。
$SIG{"INT"} = sub { say "bye"; exit }
signal(SIGINT).tap: ; loop
或者,如果您有一个想要知道它收到了哪个信号的通用代码
signal(SIGINT).tap: -> ; loop
在事件驱动情况下使用信号的更惯用方式
react
$BASETIME, $^T§
在 Raku 中被 $*INIT-INSTANT
替换。与 Perl 不同,这不是自纪元以来的秒数,而是一个 Instant
对象,它以原子秒为单位进行测量,并带有小数部分。
$PERL_VERSION, $^V§
与 $]
一样,它已被 $*RAKU.version
替换。
${^WIN32_SLOPPY_STAT}§
在 Raku 中没有类似的东西。
$EXECUTABLE_NAME, $^X§
它已被 $*EXECUTABLE-NAME
替换。请注意,还有 $*EXECUTABLE
,它是一个 Raku 中的 IO
对象。
与正则表达式相关的变量§
性能问题§
如下所示,$`
、$&
和 $'
已从 Raku 中删除,主要被 $/
的变体替换,并且随着它们的消除,Perl 中相关的性能问题不再适用。
$<digits> ($1, $2, ...)§
这些现有变量在 Raku 中的作用与在 Perl 中的作用相同,只是它们现在从 $0
开始而不是 $1
。此外,它们是匹配变量 $/
中索引项的同义词。即 $0
等效于 $/[0]
,$1
等效于 $/[1]
,等等。
$MATCH, $&§
$/
现在包含 Match
对象,因此 $&
的 Perl 行为可以通过将其字符串化来获得,即 ~$/
。
请注意,虽然 $/.Str
也应该可以工作,但 ~$/
目前是更常见的习惯用法。
${^MATCH}§
由于以前的性能问题已消除,因此此变量在 Raku 中没有用处。
$PREMATCH, $`§
被 $/.prematch
替换。
${^PREMATCH}§
由于以前的性能问题已消除,因此此变量在 Raku 中没有用处。
$POSTMATCH, $'§
被 $/.postmatch
替换。
${^POSTMATCH}§
由于以前的性能问题已消除,因此此变量在 Raku 中没有用处。
$LAST_PAREN_MATCH, $+§
在 Raku 中不存在,但您可以使用 $/[*- 1].Str
($/[*-1]
将是匹配对象,而不是实际字符串)获取相同的信息。
如果您想理解为什么它有效,您可以查看以下文档
$LAST_SUBMATCH_RESULT, $^N§
S28 建议 $*MOST_RECENT_CAPTURED_MATCH
,但似乎没有与 $^N
匹配的已实现变量。
@LAST_MATCH_END, @+§
与大多数与正则表达式相关的变量一样,此功能至少部分地转移到了 Raku 中的 $/
变量。或者,在本例中,是别名为其索引的编号变量。偏移量是通过使用 .to
方法找到的。例如,第一个偏移量是 $/[0].to
,它与 $0.to
同义。Perl 提供的 $+[0]
值由 $/.to
提供。
%LAST_PAREN_MATCH, %+§
我们再次转向 $/
。以前的 $+{$match}
是 $/{$match}
。
@LAST_MATCH_START, @-§
与 @+
被使用 .to
方法替换类似,@-
被使用 $/
及其变体上的 .from
方法替换。第一个偏移量是 $/[0].from
或等效的 $0.from
。Perl 的 $- [0]
是 $/.from
。
%LAST_MATCH_START, %-§
与 %+
非常相似,%-{$match}
的使用将被 $/{$match}
替换。
$LAST_REGEXP_CODE_RESULT, $^R§
没有等效项。
${^RE_DEBUG_FLAGS}§
没有等效项。
${^RE_TRIE_MAXBUF}§
没有等效项。
与文件句柄相关的变量§
$ARGV§
读取行时当前文件的名称可以通过 $*ARGFILES.path
获取。
@ARGV§
@*ARGS
包含命令行参数。
ARGV§
这已被 $*ARGFILES
替换。
ARGVOUT§
由于 -i
命令行开关尚未实现,因此还没有 ARGVOUT
的等效项。
$OUTPUT_FIELD_SEPARATOR, $OFS, $,§
目前没有明显的等效项。
$INPUT_LINE_NUMBER§
$NR, $.§
没有直接的替换存在。
当使用 lines 方法从 IO::Path
或 IO::Handle
类型迭代时,您可以调用其 .kv
方法以获取索引和值的交错列表(然后每次循环迭代 2 次)
for "foo".IO.lines.kv -> ,# OUTPUT:# 1: a# 2: b# 3: c# 4: d
对于 IO::CatHandle
类型(其中 $*ARGFILES
是其中之一),您可以使用 on-switch
钩子在句柄切换时重置行号,并手动递增它。另请参阅 IO::CatHandle::AutoLines
和 LN
模块,它们简化了此操作。
$INPUT_RECORD_SEPARATOR, $RS, $/§
可以通过文件句柄上的 .nl-in
方法访问它。例如 $*IN.nl-in
。
$OUTPUT_RECORD_SEPARATOR, $ORS, $\§
可以通过文件句柄上的 .nl-out
方法访问它。例如 $*OUT.nl-out
。
$OUTPUT_AUTOFLUSH, $|§
没有可用的全局替代方案。TTY 句柄默认情况下是非缓冲的,对于其他句柄,将 out-buffer 设置为零或使用 :!out-buffer
与 open 在特定 IO::Handle
上。
${^LAST_FH}§
在 Raku 中未实现。
与格式相关的变量§
Raku 中没有内置格式。
错误变量§
由于 Raku 中错误变量的改变方式,这里不会单独详细介绍它们。
引用 Raku 文档,“$! 是错误变量。”就是这样。所有错误变量似乎都被 $! 吞噬了。与 Raku 的其他部分一样,它是一个对象,它将根据错误类型或 Exception
返回不同的内容。
特别是,在处理 Exception
时,$!
提供有关抛出异常的信息,假设程序尚未停止
try# outside the catch block the exception is placed# into $!say 'outside the catch:';say $!.^name ~ ' : ' ~ $!.message;
并且上面的代码产生以下输出
within the catch:
X::AdHoc : Boooh
outside the catch:
X::AdHoc : Boooh
因此,如前所述,$!
变量保存异常对象。
与解释器状态相关的变量§
$COMPILING, $^C, $^D, ${^ENCODING}, ${^GLOBAL_PHASE}§
$^H, %^H, ${^OPEN}§
$PERLDB, $^P§
${^TAINT}§
${^UNICODE}, ${^UTF8CACHE}, ${^UTF8LOCALE}§
在 Raku 中未实现。