Perl 自适应微调子程序
通过这个例子,我想学习编写自适应子程序的最佳方法 我需要一个修剪文本的子程序(实际上,这是一个借口,我的子程序可以做任何其他事情) 为了更加通用,我希望我的子程序能够接受不同类型的参数:Perl 自适应微调子程序,perl,reference,subroutine,Perl,Reference,Subroutine,通过这个例子,我想学习编写自适应子程序的最佳方法 我需要一个修剪文本的子程序(实际上,这是一个借口,我的子程序可以做任何其他事情) 为了更加通用,我希望我的子程序能够接受不同类型的参数: my@input=('A','B','C') my@trim=trim(@input) trim(\@输入) my$out=trim($input[0])返回“A” trim(\$input[0])修剪@input的第一个元素 trim(\@a、\@b、\@c)修剪每个字符串数组 my$out=trim(\@a
my@input=('A','B','C')代码>
my@trim=trim(@input)代码>
trim(\@输入)代码>
my$out=trim($input[0])代码>返回“A”
trim(\$input[0])代码>修剪@input的第一个元素
trim(\@a、\@b、\@c)代码>修剪每个字符串数组
my$out=trim(\@a,'a,'B')代码>$out=(qw/A/B/);(行为有待讨论)
以下是我目前的丑陋解决方案:
sub trim {
state $re = qr/^\s+|\s+$/m;
my @a;
for(@_) {
if(ref eq 'SCALAR') { $$_ =~ s/$re//g; }
elsif(ref) { trim(\$_) for(@$_); }
else { push @a, s/$re//gr; }
}
return \@a if @a > 1;
return $a[0] if $a[0];
}
这个实现是否有更好的解决方案支持我上面建议的不同类型的输入
这个问题的主要原因与我的最后一个应用程序有关,在这个应用程序中,我携带的文本可以存储在字符串、字符串数组甚至散列中
我想最好写下:
trim(\@allmytexts);
align(\@allmytexts, align=>'right');
比:
这个问题离题了,可能很快就要结束了
然而,“在这样的子例程中要求这种类型的行为正确吗?”
我会说不。我还不清楚您希望这个子程序对我面前的信息做什么,而且,如果不参考您的文档,我肯定会很难记住如何调用它,如果我一两天没有使用它的话。你会发现每个人都通过写作来使用它
$string = trim($string)
因为这就是他们所记得的
看起来你自己也不清楚有些电话是干什么的,因此
my $out = trim(\@a, ' A ', ' B'); $out = (qw/A B/); (behavior to be discussed)
我猜想您已经习惯了一种具有不同传递机制的语言,类似这样的东西会很有用。在Perl中,所有内容都通过别名传递;因此,对@
数组元素的操作与对实际参数的相同操作是等价的。这意味着,如果您将任何可写值作为参数传递,则子例程可以修改该值
考虑到这一点,传递一个引用以指示它将被修改到位只不过是一个标志,指示子例程的行为方式,以及在使用该引用之前必须取消引用的限制
问问你自己,你经常看到一个常用的库函数有这样的行为。例如,分别调用index
和rindex
来执行非常类似的操作,现有的核心操作符lc
与trim
尝试执行的操作相当相似,但它只接受一个参数并返回转换后的结果sprintf
可以看作是printf
的一个变体,只要它知道,如果文件句柄参数是对标量的引用,它应该将字符串放入变量中,而不是将其写入文件句柄。但它不是那样设计的
我只能为一个已定义的问题提供另一种解决方案。你没有解释现实生活中的困难,因为你不确定你的trim
应该做什么,我怀疑是否有人能帮助你改进它
还有一件事要问你自己,当传递一个引用并修改该值时,返回值应该是什么?很明显,它应该在更改后返回值,但是,既然您正在编写自适应代码,那么如何根据调用是在标量、列表还是void上下文中更改返回值呢?或者,更好的做法是,将trim
设置为
my $n = q{ 999 };
++trim($n);
这个问题离题了,可能很快就要结束了
然而,“在这样的子例程中要求这种类型的行为正确吗?”
我会说不。我还不清楚您希望这个子程序对我面前的信息做什么,而且,如果不参考您的文档,我肯定会很难记住如何调用它,如果我一两天没有使用它的话。你会发现每个人都通过写作来使用它
$string = trim($string)
因为这就是他们所记得的
看起来你自己也不清楚有些电话是干什么的,因此
my $out = trim(\@a, ' A ', ' B'); $out = (qw/A B/); (behavior to be discussed)
我猜想您已经习惯了一种具有不同传递机制的语言,类似这样的东西会很有用。在Perl中,所有内容都通过别名传递;因此,对@
数组元素的操作与对实际参数的相同操作是等价的。这意味着,如果您将任何可写值作为参数传递,则子例程可以修改该值
考虑到这一点,传递一个引用以指示它将被修改到位只不过是一个标志,指示子例程的行为方式,以及在使用该引用之前必须取消引用的限制
问问你自己,你经常看到一个常用的库函数有这样的行为。例如,分别调用index
和rindex
来执行非常类似的操作,现有的核心操作符lc
与trim
尝试执行的操作相当相似,但它只接受一个参数并返回转换后的结果sprintf
可以看作是printf
的一个变体,只要它知道,如果文件句柄参数是对标量的引用,它应该将字符串放入变量中,而不是将其写入文件句柄。但它不是那样设计的
我只能为一个已定义的问题提供另一种解决方案。你没有解释现实生活中的困难,因为你不确定你的trim
应该做什么,我怀疑是否有人能帮助你改进它
还有一件事要问你自己,你应该做什么
$x = trim($x);
@a = map trim, @a;
sub trim_i(_) { s/^\s+|\s+\z//g for $_[0] }
trim_i($x);
trim_i for @a;
sub trim {
wantarray
? map s/^\s+|\s+\z//rg, @_
: $_[0] =~ s/^\s+|\s+\z//rg
}
$x = trim($x);
@a = trim(@a);
sub trim_i {
s/^\s+|\s+\z//rg for @_;
}
trim_i($x);
trim_i(@a);