我想将函数调用中的返回值添加到数组iff返回的内容(默认情况下不是这样,即如果我在子例程中有return
语句。)
所以我正在使用unshift @{$errors}, "HashValidator::$vfunction($hashref)";
,但这实际上是将函数调用的字符串添加到数组中。我也试过unshift @{$errors}, $temp if defined my $temp = "HashValidator::$vfunction($hashref)";
同样的结果。 perl单行看起来会有什么效果(我知道我可以进行丑陋的多行检查,但我想学习)。
谢谢,
答案 0 :(得分:2)
iff返回的东西(不是 默认,即如果我有回报 子程序中的语句。)
这里可能有问题。 Perl 总是返回一些东西,即使你不是故意:
my $failures = 0;
sub word_to_number {
my $_ = shift;
/one/ and return 1;
/two/ and return 2;
++$failures; # whoops, equivalent to return ++$failures
}
如果没有显式返回,则sub中的最后一个表达式将用作返回值。要返回“nothing”,请使用bare return,它返回undef
或空列表,具体取决于上下文:
my $failures = 0;
sub word_to_number {
my $_ = shift;
/one/ and return 1;
/two/ and return 2;
++$failures;
return;
}
此行为实际上对排序等内容非常有用:
my @results = sort { $a->name cmp $b->name } @list;
我们传递了匿名子程序:
{
$a->name cmp $b->name # equivalent to return $a->name cmp $b->name
}
答案 1 :(得分:2)
在这种情况下,无需使用eval
的字符串形式(或任何形式)。它不仅速度慢,而且还可以静默捕获错误,如果与受污染的输入一起使用,可能会导致不受信任的代码执行。要在Perl中编写虚函数调用,您可以直接使用符号表,也可以使用符号引用:
use 5.010;
use warnings;
use strict;
{package HashValidator;
sub test_ok {exists $_[0]{ok}}
sub test_fail {exists $_[0]{fail}}
}
my $hashref = {ok => 1};
my $errors;
for my $vFunction qw(test_ok test_fail) {
# to call the function:
say "glob deref: $vFunction: ", $HashValidator::{$vFunction}->($hashref);
{no strict 'refs';
say "symbolic: $vFunction: ", &{"HashValidator::$vFunction"}($hashref)}
# to conditionally use the result (if it is a true boolean value):
if (my $ret = $HashValidator::{$vFunction}->($hashref)) {
push @$errors, $ret;
}
# or to keep the function call in list context:
push @$errors, grep $_, $HashValidator::{$vFunction}->($hashref);
# or to golf it:
push @$errors, $HashValidator::{$vFunction}->($hashref) || ();
}
say @$errors.': ', join ', ' => @$errors;
打印:
glob deref: test_ok: 1
symbolic: test_ok: 1
glob deref: test_fail:
symbolic: test_fail:
3: 1, 1, 1
如果您正在使用面向对象的代码,虚拟方法调用甚至更容易,没有符号表或符号引用:
$obj->$vMethod(...)
答案 2 :(得分:1)
尝试使用eval:
push @{$errors}, eval "HashValidator::$vfunction($hashref)"
以下内容适用于perl 5.12,并检查undef返回值:
my $foo = "foo";
my $val = eval "Foo::$foo()"
push @arry,$val if ($val);