5

我很高兴得知 Perl 可以在 5.32 版本中处理链式比较

但是,我正在尝试进行链式正则表达式比较,以使我的代码更短、更清晰

#!/usr/bin/env perl

use 5.032;
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';

if (9 > 2 < 3 < 4 > 0) {
    say 'chained expressions work.'
} else {
    say 'chained expressions do not work.'
}

my $x = 4;
my $z = 4;

if ($x == 4 == $z) {
    say 'chained equality works';
}

$x = 'x';
$z = 'x';

if ($x eq 'x' eq $z) {
    say 'chained string comparisons work.';
}

$x = '.';
$z = './.';
if ($x =~ m/\./ =~ $z) { # unfortunately this doesn't work
# equivalent of `if ( ($x =~ m/\./) && ($z =~ m/\./)) {
    say 'chained regex works.';
} else {
    say 'no chained regex.'; 
}

如何正确使用正则表达式进行链式比较?

4

2 回答 2

5

虽然100 <= $x < 200有明显的含义,A =~ B =~ C但没有。哪些操作数应该是字符串?其中哪一个应该是匹配运算符?应该进行什么操作?

您建议在决赛的 RHS 上放置一个字符串=~以匹配它,但这根本不是这样的=~;该字符串始终在 LHS 上。$s =~ /a/ =~ /b/可能是有道理的,但它会做什么仍然不明显,特别是如果有捕获。因此,这不受支持。

如果您想链接一些匹配项,可以使用以下选项:

all { $s =~ $_ } qr/a/, qr/b/

any { $s =~ $_ } qr/a/, qr/b/

none { $s =~ $_ } qr/a/, qr/b/

notall { $s =~ $_ } qr/a/, qr/b/

all { /a/ } $s1, $s2

any { /a/ } $s1, $s2

none { /a/ } $s1, $s2

notall { /a/ } $s1, $s2

这些功能由核心模块List::Util提供。

于 2021-01-20T21:42:35.243 回答
3

请注意,Perl 的“链接”更像是一个宏(我个人认为,基本上重新排列代码的“语法”功能是大红旗):

$x OP1 $y OP2 $z

这被有效地重写为这样的东西(考虑了一些其他细节,但在这里并不重要):

$x OP1 $y and $y OP2 $z

这仅适用于某些运算符——进行比较的运算符。

考虑一下这个宏如果要工作的话会做什么:

$x =~ m/\./ =~ $z

这种转变为您提供:

$x =~ m/\./ and m/\./ =~ $z

也就是说,中间的东西在第一次操作时在右边,在第二次操作时在左边。$x将绑定到匹配运算符,然后匹配运算符的结果将绑定到$z,我猜这必须是预编译的模式。

ikegami 已经表明您实际上并没有链接事物。您想连续测试事物。


我通常反对这个特性,但它被立即引入 Perl,而没有经过一个实验周期。在我提出的一个相关的 Github 问题中,人们来回思考它(但请注意,对我的评论的反应数量很高,认为这会使人们感到困惑,但实际上被忽略了)。Perl 5 Thread中,有些人认为人们会感到困惑,而有些人认为这是不可能的。第二组获胜。

直到我写了链比较以避免过多的输入,以及对 Reddit 的第一条评论之后,我才对此感到困惑或反对。

但我们在这里。

我的建议是不要使用链式比较。即使文档是正确的,该功能也会让普通用户感到困惑。它不像他们想要的那样。人们倾向于根据他们所知道的其他事情来猜测编程语言会做什么。他们不是只检查每一个案例,而是凭直觉,有时是错误的,某事将或应该如何行动。

于 2021-01-21T09:52:50.073 回答