明确命名 return 值?
Explicitly named return values?
在围棋(and G++?)中,以下是一个常用的成语:
func sqr(x int) (n int, err error) {
n = x * x
err = nil
return
}
(n int, err error)
显式枚举了 return 值的名称和类型。这个我觉得有很多优点,我喜欢。
在 Perl 6 中,我们可以:
my sub sqr (Int:D $x) returns Int:D {
$x ** 2;
}
return 是隐含的,这让我有点不舒服(我们可以用 return
明确表示),但你可能会注意到 return 类型 已指定(事实上它是 D
已定义 )。
不出所料,没有明显的方法来 return 通过名称显式显示一个值,但我很好奇,因为 Perl(尤其是 6)在各个方面都可以广泛修改,如果有实现它的方法的话。 1
1 无论它多么骇人听闻,但太骇人听闻了,我会避免将它用于 "real" 事情。
如果一切都失败了,您可以随时编写自己的俚语。
但是,这里有两个我想出的不太复杂的方法,第一个使用固定名称的动态变量,第二个使用 user-defined 名称的 rw
参数:
multi sub trait_mod:<is>(Routine:D \r, :$dynrv!) {
r.wrap(-> | { my $*rv; callsame; $*rv })
}
multi sub trait_mod:<is>(Routine:D \r, :$pararv!) {
r.wrap(-> |c { my $rv; callwith(|c, $rv); $rv })
}
sub double($x) is dynrv {
$*rv = $x * 2;
return 666; # discarded
}
sub triple($x, $y is rw) is pararv {
$y = $x * 3;
return 666; # discarded
}
say double 42;
say triple 42;
请注意,这仅支持单个 return 值,但我对如何使多个值起作用有一些想法...
编辑: 例如这样:
multi sub trait_mod:<is>(Routine:D \r, :@dynrv!) {
r.wrap(-> | {
my @rv = Nil xx @dynrv;
my $*rv = Map.new(@dynrv Z=> @rv);
callsame;
@dynrv > 1 ?? @rv !! @rv[0];
})
}
multi sub trait_mod:<is>(Routine:D \r, Int :$pararv!) {
r.wrap(-> |c {
my @rv = Nil xx $pararv;
callwith(|c, |@rv);
$pararv > 1 ?? @rv !! @rv[0];
})
}
sub divmod($a, $b) is dynrv<d m> {
$*rv<d> = $a div $b;
$*rv<m> = $a mod $b;
}
sub plusmin($a, $b, $p is rw, $m is rw) is pararv(2) {
$p = $a + $b;
$m = $a - $b;
}
say divmod 14, 3;
say plusmin 14, 3;
虽然可以使用俚语准确地获得您想要的内容,但我认为它们是解决此问题的错误尺寸解决方案。首先,cat 的 Go 示例是 returning 错误信息以及一个 (Int)。我建议 Perl 6 的方法是简单地 return 一个 Fail 对象使用 &fail
调用者可以测试使用 .defined
或//
运算符;
if $something_wrong {
return fail "Dang! Even the squaring function isn't working today."
}
else {
return $x ** 2
}
我知道这不会按要求记录双重 return 值,但是您要为特殊的带外数据使用显式变量吗?如果不是错误数据而是其他信息怎么办?
假设我们想要 return 一个带有复活节彩蛋消息的 (Int)。在这种情况下,由于额外的数据是不同的类型,(Str),我们可以 运行 时间将角色与 .Str
方法混合,如果 return 消息35=] 值在字符串上下文中使用。
return $x * $x but "Suprise! Bet you weren't expecting that!"
或者,如果额外数据属于同一类型,我们可以显式混合一个匿名角色。假设我们想要 return 一个带有 .size
属性;
的 (Int)
return $x but role { has $.size = calculate_size() }
最后,您可以通过声明角色然后使用子集来定义需要该角色的您自己的 (Int) 类型来显式记录您的 return 类型;
role Size { has UInt:D $.size = 0 }
subset MyInt of Int where Size;
sub sqr(Int:D $x, UInt:D :$size = 12) returns MyInt:D {
return $x * $x but Size($size)
}
my $square5 = sqr(5);
say "5 squared is $square5 with size $square5.size()."
# prints: 5 squared is 25 with size 12.
详情见S14 and S12 - Anonymous mixin roles
在围棋(and G++?)中,以下是一个常用的成语:
func sqr(x int) (n int, err error) {
n = x * x
err = nil
return
}
(n int, err error)
显式枚举了 return 值的名称和类型。这个我觉得有很多优点,我喜欢。
在 Perl 6 中,我们可以:
my sub sqr (Int:D $x) returns Int:D {
$x ** 2;
}
return 是隐含的,这让我有点不舒服(我们可以用 return
明确表示),但你可能会注意到 return 类型 已指定(事实上它是 D
已定义 )。
不出所料,没有明显的方法来 return 通过名称显式显示一个值,但我很好奇,因为 Perl(尤其是 6)在各个方面都可以广泛修改,如果有实现它的方法的话。 1
1 无论它多么骇人听闻,但太骇人听闻了,我会避免将它用于 "real" 事情。
如果一切都失败了,您可以随时编写自己的俚语。
但是,这里有两个我想出的不太复杂的方法,第一个使用固定名称的动态变量,第二个使用 user-defined 名称的 rw
参数:
multi sub trait_mod:<is>(Routine:D \r, :$dynrv!) {
r.wrap(-> | { my $*rv; callsame; $*rv })
}
multi sub trait_mod:<is>(Routine:D \r, :$pararv!) {
r.wrap(-> |c { my $rv; callwith(|c, $rv); $rv })
}
sub double($x) is dynrv {
$*rv = $x * 2;
return 666; # discarded
}
sub triple($x, $y is rw) is pararv {
$y = $x * 3;
return 666; # discarded
}
say double 42;
say triple 42;
请注意,这仅支持单个 return 值,但我对如何使多个值起作用有一些想法...
编辑: 例如这样:
multi sub trait_mod:<is>(Routine:D \r, :@dynrv!) {
r.wrap(-> | {
my @rv = Nil xx @dynrv;
my $*rv = Map.new(@dynrv Z=> @rv);
callsame;
@dynrv > 1 ?? @rv !! @rv[0];
})
}
multi sub trait_mod:<is>(Routine:D \r, Int :$pararv!) {
r.wrap(-> |c {
my @rv = Nil xx $pararv;
callwith(|c, |@rv);
$pararv > 1 ?? @rv !! @rv[0];
})
}
sub divmod($a, $b) is dynrv<d m> {
$*rv<d> = $a div $b;
$*rv<m> = $a mod $b;
}
sub plusmin($a, $b, $p is rw, $m is rw) is pararv(2) {
$p = $a + $b;
$m = $a - $b;
}
say divmod 14, 3;
say plusmin 14, 3;
虽然可以使用俚语准确地获得您想要的内容,但我认为它们是解决此问题的错误尺寸解决方案。首先,cat 的 Go 示例是 returning 错误信息以及一个 (Int)。我建议 Perl 6 的方法是简单地 return 一个 Fail 对象使用 &fail
调用者可以测试使用 .defined
或//
运算符;
if $something_wrong {
return fail "Dang! Even the squaring function isn't working today."
}
else {
return $x ** 2
}
我知道这不会按要求记录双重 return 值,但是您要为特殊的带外数据使用显式变量吗?如果不是错误数据而是其他信息怎么办?
假设我们想要 return 一个带有复活节彩蛋消息的 (Int)。在这种情况下,由于额外的数据是不同的类型,(Str),我们可以 运行 时间将角色与 .Str
方法混合,如果 return 消息35=] 值在字符串上下文中使用。
return $x * $x but "Suprise! Bet you weren't expecting that!"
或者,如果额外数据属于同一类型,我们可以显式混合一个匿名角色。假设我们想要 return 一个带有 .size
属性;
return $x but role { has $.size = calculate_size() }
最后,您可以通过声明角色然后使用子集来定义需要该角色的您自己的 (Int) 类型来显式记录您的 return 类型;
role Size { has UInt:D $.size = 0 }
subset MyInt of Int where Size;
sub sqr(Int:D $x, UInt:D :$size = 12) returns MyInt:D {
return $x * $x but Size($size)
}
my $square5 = sqr(5);
say "5 squared is $square5 with size $square5.size()."
# prints: 5 squared is 25 with size 12.
详情见S14 and S12 - Anonymous mixin roles