明确命名的返回值?

cat*_*cat 4 return-value perl6

在Go(和G ++?)中,以下是一个常见的习语:

func sqr(x int) (n int, err error) {
    n = x * x
    err = nil
    return
}
Run Code Online (Sandbox Code Playgroud)

(n int, err error)明确列举了返回值的名称和类型.在我看来,这有很多优点,我喜欢它.


在Perl 6中,我们可以:

my sub sqr (Int:D $x) returns Int:D {
    $x ** 2;
}
Run Code Online (Sandbox Code Playgroud)

返回是隐式的,这让我有点不舒服(我们可以明确表示return),但你可能会注意到指定了返回类型(因为它已被D定义).

不出所料,没有明显的方法可以通过名称显式返回值,但我很好奇,因为Perl(尤其是6)在各方面都可以进行广泛修改,如果有办法实现这一点的话.1


1然而,它可能是hacky,但太过于hacky而且我会避免将它用于"真实"的东西.

Chr*_*oph 7

如果一切都失败了,你总是可以写自己的俚语.

但是,这里提到了两个不太复杂的方法,第一个使用固定名称的动态变量,第二个使用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;
Run Code Online (Sandbox Code Playgroud)

请注意,这只支持单个返回值,但我有一些想法可以使多个可以工作...


编辑:例如这样:

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;
Run Code Online (Sandbox Code Playgroud)

  • 这太棒了*.这是**疯狂**,但它真棒. (2认同)