Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在这个perl代码中,$\在哪里被修改?_Perl_Natural Sort_Perl Critic - Fatal编程技术网

在这个perl代码中,$\在哪里被修改?

在这个perl代码中,$\在哪里被修改?,perl,natural-sort,perl-critic,Perl,Natural Sort,Perl Critic,以下perl代码以PerlCritic(按Activestate)生成警告: 生成的警告是: 不要在列表函数中修改$ 我不理解这个警告,因为我不认为我在修改$\ux,尽管我想我必须这样做。 有人能给我解释一下吗?你在grep中做一个替换(即s//),它修改$,即列表被格雷格化。你的grep都在修改$\ucode>,因为你正在使用s/。例如,这: grep {s/(^|\D)0+(\d)/$1$2/g,1} 与此相同: grep { $_ =~ s/(^|\D)0+(\d)/$1$2/g; 1

以下perl代码以PerlCritic(按Activestate)生成警告:

生成的警告是:

不要在列表函数中修改$

我不理解这个警告,因为我不认为我在修改$\ux,尽管我想我必须这样做。
有人能给我解释一下吗?

你在grep中做一个替换(即
s//
),它修改
$,即列表被格雷格化。

你的
grep
都在修改
$\ucode>,因为你正在使用
s/
。例如,这:

grep {s/(^|\D)0+(\d)/$1$2/g,1}
与此相同:

grep { $_ =~ s/(^|\D)0+(\d)/$1$2/g; 1 }
我认为您最好使用
map
,因为您没有使用
grep
s过滤任何内容,您只是使用
grep
作为迭代器:

sub natural_sort {
    my $t;
    return map { ($t = $_) =~ s/(^|\D)0+(\d)/$1$2/g; $t }
           sort
           map { ($t = $_) =~ s/(\d+)/sprintf"%06.6d",$1/ge; $t }
           @_;
}

这应该做同样的事情,让批评家保持沉默。如果您想要一些比普通的
map

更好的列表运算符,您可能需要了解一下这一情况和其他情况的解释如下:

下面是Perl将要使用的地方 假设$u,即使您不使用它:

  • 以下功能:
防抱死制动系统,警报,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声,嘎嘎声, cos,defined,eval,exp,glob,hex, int,lc,lcfirst,length,log,lstat, mkdir、oct、ord、pos、打印、, quotemeta、readlink、readpipe、ref、, require,reverse(在标量上下文中) 仅),rmdir,sin,split(在其上) 第二个参数),sqrt,统计,研究, uc,ucfirst,取消链接,解包

  • 除了-t(默认为STDIN)之外的所有文件测试(-f,-d)。 见-X

  • 模式匹配操作m//、s//和tr//(也称为y//)在 不带=~运算符使用

  • 如果未指定其他变量,则foreach循环中的默认迭代器变量 供应

  • grep()和map()函数中的隐式迭代器变量

  • 给定()的隐式变量

  • 当操作的结果失败时放置输入记录的默认位置 作为唯一的测试工具进行测试
    一段时间测试的标准。在a之外
    在测试期间,这不会发生


其他答案遗漏的非常重要的部分是这条线

grep {s/(\d+)/sprintf"%06.6d",$1/ge,1} @_;
实际上是修改传递到函数中的参数,而不是它们的副本

grep
是一个过滤命令,代码块内的
$\u
中的值是
@
中一个值的别名
@
又包含传递给函数的参数的别名,因此当
s///
运算符执行其替换时,会对原始参数进行更改。如下例所示:

sub test {grep {s/a/b/g; 1} @_}

my @array = qw(cat bat sat);

my @new = test @array;

say "@new";   # prints "cbt bbt sbt" as it should
say "@array"; # prints "cbt bbt sbt" as well, which is probably an error
您正在寻找的行为(将修改列表副本的函数应用于列表副本)已封装为许多模块中的
apply
函数。我的模块包含这样一个实现<代码>应用
也很容易自己编写:

sub apply (&@) {
    my ($sub, @ret) = @_;
    $sub->() for @ret;
    wantarray ? @ret : pop @ret
}
这样,您的代码可以重写为:

sub natural_sort {
    apply {s/(^|\D)0+(\d)/$1$2/g} sort apply {s/(\d+)/sprintf"%06.6d",$1/ge} @_
}

如果重复替换的目标是在应用临时修改的情况下执行一种原始数据,那么您应该研究一种称为的Perl惯用法,它是实现该目标的更有效的方法。

许多人正确地回答了
s
操作符正在修改
$\ucode>,然而,在即将发布的Perl 5.14.0中,
s
操作符(即
s///r
)将使用新的
r
标志,它将返回修改后的元素,而不是就地修改。阅读更多信息。您可以使用安装此新版本

编辑:Perl 5.14现在可用

以下是mu建议的功能(使用
map
),但使用此功能:

use 5.14.0;

sub natural_sort {
    return map { s/(^|\D)0+(\d)/$1$2/gr }
           sort
           map { s/(\d+)/sprintf"%06.6d",$1/gre }
           @_;
}

我将研究一下这个习惯用法,但是考虑到我的数据,修改参数是可以接受的。@Craig=>如果是非故意的,修改参数是永远不能接受的。如果几个月后,您需要对常量数组或将再次使用的数组使用排序,该怎么办?明白您的意思,但这不会发生,我说过我会看看这个习惯用法
use 5.14.0;

sub natural_sort {
    return map { s/(^|\D)0+(\d)/$1$2/gr }
           sort
           map { s/(\d+)/sprintf"%06.6d",$1/gre }
           @_;
}