我有一个函数sub _where(\@ \&)
,它有两个参数:第一个是数组,第二个应该是另一个函数。这个其他函数返回一个布尔值,我想在sub _where(\@ \&)
函数的for循环中调用它。
我无法将我传入的函数解压缩为自定义本地名称。我想我确实需要一些本地名称,因为应该可以将不同的布尔函数传递给我的where
函数。
其中:
sub _where(\@ \&)
{
my @stud = @{$_[0]};
my $student;
my $function = shift;
my $bool = 0;
my $i;
for $i(0..$#stud)
{
my $student = $stud[$i];
function $student;
}
}
应该传递的Function1:
sub name_starts_with($)
{
my $letter = 'B';
my $student = shift;
my $first;
$first = substr($student -> name, 0, 1);
if($first eq $letter)
{
return 1;
}
}
应传递给where
的函数2:
sub points_greater_than($)
{
my $sum_pts = 5;
my $student = shift;
my $pts;
$pts = $student -> points;
if($pts > $sum_pts)
{
return 1;
}
}
希望你们能在这里帮助我。干杯
答案 0 :(得分:3)
你不应该使用原型。它们在Perl中的工作方式与其他语言不同,几乎不是一个好的选择。
除非要在不影响外部数据的情况下进行修改,否则还应避免制作传入数组的本地副本。
最后,以下划线开头的子例程名称通常表示它是类的私有方法。这看起来不像这样。
您的代码应如下所示
sub _where {
my ($stud, $function) = @_;
my $student;
my $bool = 0;
for my $i (0..$#stud) {
my $student = $stud->[$i];
$function->($student);
}
}
然后你可以把它称为
_where(\@student, \&function);
答案 1 :(得分:2)
问题在于如何获得参数:
my @stud = @{$_[0]}; # <-- this doesn't remove first parameter from list
my $student;
my $function = shift; # <-- therefore you'll still get first parameter, not second
尝试此修复:
my $function = $_[1]; # always get second parameter
<强>更新强>
添加如何将函数的引用传递给其他函数的示例:
_where(\@stud, \&name_starts_with);
答案 2 :(得分:1)
您在函数_where
中的参数处理存在错误。您将数组引用放入$function
变量。你必须这样做
my @stud = @{shift()};
my $student;
my $function = shift();
或
my @stud = @{$_[0]};
my $student;
my $function = $_[1];
或者我更喜欢
sub _where(\@ \&)
{
my ($stud, $function) = @_;
for my $student (@$stud)
{
$function->($student);
}
}
但不要混用这些方法。
答案 3 :(得分:1)
通过抓取第一个参数解决问题之后,以下是从代码引用中调用子例程的三种方法:
&$function($student); # uses the fewest characters!
&{$function}($student); # the style you're using for the array ref
$function->($student); # my favorite style
您可以通过阅读perlref手册页找到更多详细信息。
答案 4 :(得分:1)
您似乎试图在Perl中编写另一种语言。伊克。试试这个:
sub _where
{
my $students = shift;
my $function = shift;
$function->($_) for @$students;
}
sub name_starts_with
{
my $student = shift;
my $letter = 'B';
my $first = substr($student->name, 0, 1);
return $first eq $letter; # same as 'return $first eq $letter ? 1 : undef;'
}
sub points_greater_than
{
my $student = shift;
my $sum_pts = 5;
my $pts = $student->points;
return $pts > $sum_pts;
}
您可以将其称为_where(\@students, \&name_starts_with)
。
但是我并不完全是你的_where函数的目的是什么,因为它没有返回任何内容(除了评估的最后一个语句,在这个上下文中似乎没有用)。
也许你只想要grep?
my @students_b = grep { substr($_->name, 0, 1) eq 'B' } @students;
答案 5 :(得分:1)
如果您更改参数的顺序以使coderef成为第一个,那么您的代码将会更加Perlish。
sub _where(\&@){
my $func = shift;
my @return;
for(@_){
push @return, $_ if $func->($_);
}
return @return;
}
如果你精通Perl,你会注意到我刚刚重新实现grep
(很差)。
sub name_starts_with{
'B' eq substr($_->name, 0, 1);
}
sub points_greater_than{
$_->points > 5;
}
my @b_students = _where( &name_starts_with, @students );
my $count_of_students_above_5 = _where( &points_greater_than, @students );
my @b_students = grep( &name_starts_with, @students );
my $count_of_students_above_5 = grep( &points_greater_than, @students );
由于这些子程序也非常短,所以只使用一个块。
my @b_students = grep {
'B' eq substr($_->name, 0, 1)
} @students;
my $count_of_students_above_5 = grep {
$_->points > 5;
} @students;