描述§

一个(希望是)全面的 Perl 运算符列表,以及它们在 Raku 中的等效项,并在必要时说明它们之间的差异。

注意§

本文档详细解释运算符。本文档旨在指导您从 Perl 的 perlop 文档中的运算符到 Raku 中的等效运算符。有关 Raku 等效运算符的完整文档,请参阅 Raku 文档

运算符优先级和结合性§

Raku 中的运算符优先级表与 Perl 中有所不同,因此这里不会详细介绍。如果您需要了解 Raku 中特定运算符的优先级和结合性,请参阅 运算符优先级

术语和列表运算符§

在本节中,Perl 的 perlop 文档中列出的作为一元和列表运算符的内容,往往可以被视为函数,例如 printchdir。因此,您可以在 函数 指南中找到有关它们的信息。括号仍然用于分组。有一个注意事项:在 Raku 中,是 ,(逗号)创建列表,不是括号。所以

my @foo = 1,2,3,4,5;   # no parentheses needed 
.say for 1,2,3,4,5;    # also no parentheses 
 
my $scalar = (1);      # *not* a list, as there is no comma 
my $list   = (1,);     # a List in a scalar container 

箭头运算符§

由于您通常不会在 Raku 中使用引用,因此箭头可能作为解引用运算符不太有用。但是,如果您确实需要解引用某些内容,则箭头是点。它也是方法调用的点。因此,Perl 中的 $arrayref->[7] 在 Raku 中变为 $arrayref.[7],类似地,$user->name 变为 $user.name=> 箭头用于构建 Pair,请参阅 Pair 术语文档

自动递增和自动递减§

与 Perl 中的工作方式相同。唯一可能的注意事项是它们通过调用 succ 方法(对于 ++)和 pred 方法(对于 --)来实现。对于内置数值类型,这不太可能做一些不寻常的事情,但自定义类型可以定义自己的 succpred 方法,因此在这些情况下,您可能应该注意 ++--实际执行的操作。

指数运算§

按预期工作。Perl 中的 perlop 关于 ** 绑定比一元减号更紧密(即 "-2**4" 评估为 "-(2**4)" 而不是 "(-2)**4")的注意事项也适用于 Raku。

符号一元运算符§

与 Perl 中一样,一元 !- 分别执行逻辑和算术否定。?^ 用于按位逻辑否定,文档表明它等效于 !。需要注意的是,它们会将它们的参数分别强制转换为 BoolNumeric

一元 ~ 是 Raku 中的字符串上下文运算符,因此使用前缀 +^ 进行按位整数否定。假设是二进制补码。

+ 在 Raku 中确实有作用,它将它的参数强制转换为 Numeric 类型。

一元 \ 不再存在。如果您真的想对现有的命名变量取一个“引用”,您可以使用项目上下文,如下所示:$aref = item(@array),或者可能更熟悉地通过添加前缀 $$aref = $@array。请注意,您实际上并没有获得引用,而是获得一个包含引用对象的标量容器。

您可以通过使用 & 符号获得对命名子例程的“引用”:$sref = &foo。匿名数组、哈希和子例程在创建时立即返回底层对象:$sref = sub { }

绑定运算符§

=~!~ 分别被 ~~!~~ 替换。那些认为智能匹配在 Perl 中有缺陷的人会很高兴地听到它在 Raku 中工作得更好,因为更强的类型意味着更少的猜测。请参阅 智能匹配文档,以更详细地了解智能匹配在 Raku 中的工作原理。

乘法运算符§

二元运算符 */% 分别表示乘法、除法和取模运算,与 Perl 中相同。

二元运算符 x 在 Raku 中略有不同,并且有一个伴随运算符。print '-' x 80; 会生成一个包含 80 个连字符的字符串,但要实现 Perl 中 @ones = (1) x 80; 的行为,即生成一个包含 80 个“1”的列表,则需要使用 @ones = 1 xx 80;

加法运算符§

二元运算符 +- 分别表示加法和减法,与预期一致。

由于 . 是方法调用运算符,因此二元运算符 ~ 在 Raku 中充当连接运算符。

移位运算符§

<<>> 已被 +<+> 替换。

命名一元运算符§

如上所述,您可以在 函数 指南中找到这些运算符。

关系运算符§

这些运算符在 Raku 中与 Perl 中相同。

相等运算符§

==!= 在 Raku 中与 Perl 中相同。

<=>cmp 在 Raku 中的行为有所不同。<=> 执行数值比较,但返回 Order::LessOrder::SameOrder::More,而不是 Perl 中的 -101。要获得 Perl 中 cmp 的行为(更改为返回 Order 对象,而不是整数),可以使用 leg 运算符。

cmp 会根据其参数的现有类型执行 <=>leg

~~ 是 Perl 中的智能匹配运算符,但它在 Raku 中也是仅仅匹配运算符,如上所述。有关 Raku 中智能匹配的工作原理,请参阅 智能匹配文档

智能匹配运算符§

有关 Raku 中智能匹配的工作原理的更详细解释,请参阅 智能匹配文档

按位与§

二元运算符 & 在 Raku 中为 +&

按位或和异或§

按位或运算符已从 Perl 中的 | 更改为 Raku 中的 +|。类似地,按位异或运算符 ^+^,但它仅对整数进行操作。

C 风格逻辑与§

未更改。

C 风格逻辑或§

未更改。

逻辑定义或§

在 Raku 中保持为 //。返回第一个定义的操作数,否则返回最后一个操作数。此外,还有一个低优先级版本,称为 orelse

范围运算符§

在列表上下文中,.. 充当范围运算符,无需更改。也就是说,存在可能很有用的排他范围运算符。它们是

  • 中缀 ..^,它不包含终点;

  • 中缀 ^..,它不包含起点;

  • 中缀 ^..^,它不包含起点和终点;

  • 前缀 ^,它从零开始,不包含终点。

以下示例展示了所有上述范围运算符的效果(请注意,括号仅用于允许方法调用)

(1..^5).list;  # (1 2 3 4) 
(1^..5).list;  # (2 3 4 5) 
(1^..^5).list# (2 3 4) 
(^5).list;     # (0 1 2 3 4) 

在 Perl 中,在标量上下文中,运算符 ..... 充当翻转操作符,即使它们鲜为人知且可能使用较少。这些运算符在 Raku 中分别被 fffff 替换。

条件运算符§

条件运算符 ? : 已被 ?? !! 替换。

$x = $ok  ? $yes  : $no;  # Perl

$x = $ok ?? $yes !! $no;  # Raku 

赋值运算符§

虽然没有完全记录,但 S03 指示数学和逻辑赋值运算符应按预期工作。一个明显的变化是 .= 在左侧的对象(也可以是类型对象)上调用一个可变方法。这允许以下有用的习惯用法

class LongClassName {
    has $.frobnicate;
}
my LongClassName $bar .= newfrobnicate => 42 ); # no need to repeat class name 

这确保 $bar 只能包含 LongClassName 对象,并且不必重复(以及可能拼错)类名。

~= 是字符串连接赋值,正如您在 .~ 的变化中所预期的那样。此外,位赋值运算符可能不会被分成数字和字符串版本(&= 等,与 &.= 等),因为该功能目前在 Perl 本身中是实验性的 - 尽管,同样,这没有具体记录。

逗号运算符§

逗号运算符的工作方式与预期基本一致,但从技术上讲它创建 列表)或在函数调用中分隔参数。此外,还有一个 : 变体,它将函数调用转换为方法调用 - 请参阅 此页面

=> 运算符或胖箭头,与 Perl 的“胖逗号”类似,它允许在其左侧使用未加引号的(普通)标识符,但在 Raku 中构造 Pair 对象,而不仅仅是充当分隔符。如果您只是尝试将一行 Perl 代码逐字翻译成 Raku,它应该按预期工作。要阅读 Raku,请查看 副词对,它将解释一种新的语法。

列表运算符(向右)§

与命名一元运算符一样,您将在 函数 中找到对它们的讨论。

逻辑非§

! 的较低优先级版本。与 ! 一样,它将参数强制转换为 Bool

逻辑与§

&& 的较低优先级版本,与 Perl 中一样。

逻辑或和异或§

or|| 的低优先级版本,xor^^ 的低优先级版本。

此外,还有一个 // 的低优先级版本,称为 orelse

引号和类似引号的运算符§

有关引号构造的所有详细信息,请参阅 引号

有一个引号运算符允许绝对字面字符串:Q「…」,尽管后者可能难以在您的键盘上找到,具体取决于您的键盘... 反斜杠转义符在 Q 引号字符串中适用。例如,Q{This is still a closing curly brace → \} 呈现“This is still a closing curly brace → \”。

q 按照您的预期执行,允许反斜杠转义。例如,q{This is not a closing curly brace → \}, but this is → } 返回“This is not a closing curly brace → }, but this is →”。与 Perl 中一样,您可以使用单引号获得此行为。

qq 允许变量插值。但是,默认情况下,只有标量变量会被插值。要使其他变量插值,需要在它们后面加上方括号(所谓的 zen-slice)才能使它们插值。例如,@a = <1 2 3>; say qq/@a[] [email protected]/; 的结果是 "1 2 3 [email protected]"。哈希以相同的方式插值:%a = 1 => 2, 3 => 4;say "%a{}"; 的结果是使用空格分隔键值对,使用制表符分隔每个键值对中的键和值(因为这是 Pair 的标准字符串化方式,并且哈希在字符串化时充当 Pair 列表)。您也可以使用花括号在字符串中插值 Raku 代码。有关所有详细信息,请参阅 插值

qw 的工作方式与 Perl 中相同,也可以渲染为 <...>。例如,qw/a b c/ 等效于 <a b c>

还有一个插值的 qw 版本,即 qqw。因此,my $a = 42;say qqw/$a b c/; 将为您提供 "42 b c"。

Shell 引用可以通过 qx 获得,但您应该注意,反引号不像 Perl 中那样进行 shell 引用,并且 Perl 变量不会在 qx 字符串中插值。如果您需要在 shell 命令字符串中插值 Perl 变量,可以使用 qqx 代替。

qr 运算符已从 Raku 中移除。

tr/// 的工作方式与 Perl 中类似。唯一需要注意的是范围的指定方式不同。您不会使用范围 "a-z",而是使用 "a..z",即使用 Perl 的范围运算符。tr/// 有一个方法版本,它有更好的文档,称为 .trans.trans 使用一对列表,如下所示:$x.trans(['a'..'c'] => ['A'..'C'], ['d'..'q'] => ['D'..'Q'], ['r'..'z'] => ['R'..'Z']);。有关 .trans 用法的更详细说明,请参阅 https://design.raku.org/S05.html#Transliterationy/// 等效项已被移除。

Heredoc 在 Raku 中的指定方式不同。您使用 :to 与您的引用运算符一起使用,例如,q:to/END/; 将启动一个以 "END" 结尾的 heredoc。类似地,您会根据您的引用运算符获得转义和插值,即使用 Q 进行字面量,使用 q 进行反斜杠转义,使用 qq 进行插值。

I/O 运算符§

有关 Raku 中输入/输出的完整详细信息,请参阅 io

由于 <...> 是 Raku 中的引用词构造,因此 <> 不用于从文件读取行。您可以通过从文件名创建 IO 对象或使用打开的文件句柄来实现,然后在任一情况下,都可以在其上调用 .lines。例如,my @a = "filename".IO.lines;my $fh = open "filename", :r;my @a = $fh.lines;(在后一种情况下,我们使用 :r 特别是打开文件以供读取)。要以迭代方式执行此操作,您可以使用 for 循环,方法如下

for 'huge-csv'.IO.lines -> $line {
    # Do something with $line 
}

请注意那里的 -> 的使用。这是 Block 语法的一部分,在 Raku 中,对于 ifforwhile 等是必需的。

如果您想将整个文件吸收到标量中,您将 - 令人惊讶!- 使用 .slurp 方法。例如

my $x = "filename".IO.slurp;
# ... or ... 
my $fh = open "filename":r;
my $x = $fh.slurp;

特殊变量 指南中所述,ARGV 魔法输入文件句柄已被 $*ARGFILES 替换,命令行参数的 @ARGV 数组已被 @*ARGS 替换。

无操作§

1 while foo(); 的工作方式与 Perl 中相同,但会生成警告。在 Raku 中,该习惯用法现在写为 Nil while foo();

按位字符串运算符§

在上面单独记录,但总结一下...

按位整数取反是前缀 +^。按位布尔取反是 ?^

按位与是 +&

按位整数或为 +|。按位整数异或为中缀 +^。按位布尔或为 ?|

左移和右移分别是 +<+>