这符合我的期望。 fib(13)返回233。
sub fib(Int $a --> Int) {
return 0 if $a == 0;
return 1 if $a == 1;
return fib($a -1) + fib($a -2);
}
my $square = -> $x { $x * 2 }; # this works with no return value
my @list = <1 2 3 4 5 6 7 8 9>.map( $square );
# returns [2 4 6 8 10 12 14 16 18]
我尝试使用匿名子实现fib()
my $fib = -> Int $x --> Int {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
$fib(13)
运行带有显式返回的错误。
试图返回任何例程之外 在test.p6第39行处的方块中
所以我摆脱了返回值。
my $fib = -> Int $x --> Int {
0 if $x == 0;
1 if $x == 1;
$fib($x - 1) + $fib($x - 2);
}
say $fib(13);
此最新版本永不返回。有没有办法编写没有返回值的匿名递归函数?
答案 0 :(得分:9)
不是Routine类型的块(这是Block的子类)是 透明即可返回。
sub f() { say <a b c>.map: { return 42 }; # ^^^^^^ exits &f, not just the block }
最后一条语句是该块的隐式返回值
因此您可以尝试:
my $fib = -> Int $x --> Int {
if ( $x == 0 ) {
0; # <-- Implicit return value
}
elsif ( $x == 1 ) {
1; # <-- Implicit return value
}
else {
$fib($x - 1) + $fib($x - 2); # <-- Implicit return value
}
}
答案 1 :(得分:7)
另外三个选项:
sub
您可以使用不带名称的sub
来编写匿名例程:
my $fib = sub (Int $x --> Int) {
return 0 if $x == 0;
return 1 if $x == 1;
return $fib($x - 1) + $fib($x - 2);
}
say $fib(13); # 233
请参阅@HåkonHægland的答案,以了解为什么此(故意)不适用于非常规块。
leave
设计预期了您的问题:
my $fib = -> Int $x --> Int {
leave 0 if $x == 0;
leave 1 if $x == 1;
leave $fib($x - 1) + $fib($x - 2);
}
编译。希望您能猜到它所做的-或更确切地说is supposed to do-正是您想要做的。
不幸的是,如果您按照以下步骤操作:
say $fib(13);
您收到运行时错误“尚未执行”。
我的猜测是,这将在未来几年内实现,并且“尝试返回任何例行程序之外”错误消息将提到leave
。但是实现它的优先级非常低,因为如上所述很容易编写sub
,或者像@HåkonHægland那样编写代码,或者按如下所述使用case / switch语句构造,这已经足够了。
when
/ default
)您可以将参数指定为$_
而不是$x
,然后就可以使用引用该主题的构造了。
my $fib = -> Int $_ --> Int {
when 0 { 0 }
when 1 { 1 }
$fib($_ - 1) + $fib($_ - 2)
}
say $fib(13); # 233
请参见when
。
答案 2 :(得分:4)
Blocks don't need to declare the return type。不过,您仍然可以返回任何所需的东西。问题不在于使用return,而是在Int的声明中。
use v6;
my $fib = -> Int $x {
if $x == 0 {
0;
} elsif $x == 1 {
1;
} else {
$fib($x - 1) + $fib($x - 2);
}
}
say $fib(13) ;
问题在于返回值必须是最后执行的值。按照您执行的方式,如果找到0或1,它将继续运行,直到最后一条语句,该语句将重新开始。
另外,您可以使用given
代替级联的ifs。只要返回的是最后一次发出,就可以了。