在 Python 3 中,假设您开设了一门课程,并在学期结束时决定放弃第一个和最后一个作业成绩,而只计算其余成绩的平均值:
def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)
print drop_first_last([100,68,67,66,23]);
在 Perl 6 中:
sub drop_first_last(@grades) {
my ($first, *@middle, $last) = @grades;
return avg(@middle);
}
say drop_first_last(100,68,67,66,23);
导致错误“无法在可变参数之后放置所需参数
$last
”。
那么,Perl 6 中与 Python 中的星号表达式等效的表达式是什么?
sub drop_first_last(Seq() \seq, $n = 1) { seq.skip($n).head(*-$n) };
say drop_first_last( 1..10 ); # (2 3 4 5 6 7 8 9)
say drop_first_last( 1..10, 2 ); # (3 4 5 6 7 8)
它的工作方式:将第一个参数转换为
Seq
,然后跳过 $n
元素,然后保留除最后 $n
元素之外的所有元素。
Perl5:
sub drop_first_last { avg( @_[ 1 .. $#_-1 ] ) } #this
sub drop_first_last { shift;pop;avg@_ } #or this
Perl6:
sub drop_first_last { avg( @_[ 1 .. @_.end-1 ] ) }
使用一片。
sub drop_first_last (@grades) {
return avg(@grades[1..*-2])
}
答案其余部分中显示的解决方法是正确的,但对您问题的简短回答是,Perl 6 中没有与 Python 中的
*
等效的表达式。
这种类型的参数通常被称为可变参数,在 Perl 6 中被称为 *slurpy+,因为它们 slurp 参数的 rest。这就是关键,其余。子例程签名中的模糊参数之后不能声明任何参数。下面的示例也使用了一种解决方法:
sub avg( @grades ) {
return ([+] @grades) / +@grades;
}
sub drop_first_last($first, *@other-grades) {
return avg(@other-grades[0..*-1]);
}
my @grades = <10 4 8 9 10 8>;
say drop_first_last( |@grades );
but 首先在签名中使用 slurpy
*
来展示它是如何工作的,然后,通过使用 |@grades
调用它,是 flattening 数组而不是将其绑定到数组参数中。所以长的答案是,Perl 6 中的签名中实际上有一个 *
或可变参数符号,它的工作方式与 Python 中的类似,但它只能放在这些签名的最后,因为它捕获了 表达式元素的其余。
如果由于其他原因需要第一个和最后一个值, 切片内未展平的列表结构映射到结果 在大多数情况下,所以你可以这样做(你必须在 $middle 以防止自动展平):
my @grades = (1,2,3,4,5,6);
my ($first, $middle, $last) = @grades[0,(0^..^*-1),*-1];
$first.say; $middle.say; $last.say;
#1
#(2 3 4 5)
#6