我们可以做得更多

We can do more

DataKinds 继续着他对 Python 之道的教育翻译,以蝴蝶的方式。他的追求是展示如何在 Raku 中做一些在 Python 中完成的事情。一如既往,TIMTOWTDI 适用

从这些例子可以看出,Raku 不缺少 Python 能提供的任何东西。很高兴知道这一点,但是如果你不能做更多的事情,你为什么要转换呢?所以,让我们来探索一下 Raku 能做得更好的地方。

对于一个 Positional 容器,我们希望将每个偶数元素与每个不偶数元素进行切换。将元素1与元素2翻转,然后将元素3与元素4翻转,以此类推。我们还希望为不可能做到这一点的情况提供一个合理的错误信息。Rakudo 提供并使用 X::Parameter 命名空间。所以我们的自定义异常自然而然地就出现在这里了。

class X::Parameter::UnevenElementList is Exception {
    method message {
        'Positional with uneven elements in where clause.'
    }
}

现在,我们需要一个 sub,在一个位置参数中取一个 Positional,并对其进行类型检查。我们将把这个类型检查移到一个名字恰当的 sub 中。如果没有必要,我们不需要降低可读性。在 where 子句中使用 Callable 容器在文档中没有。我稍后会检查 Roast,如果需要的话,我会提交一个问题。

sub swap-each-pair(@a is raw where &check-for-even-elements ) {
    sub check-for-even-elements {
        .elems %% 2
        || X::Parameter::UnevenElementList.new.throw
    }

    for @a <-> $a, $b {
        ($a, $b) = ($b, $a)
    }
}

my @l = 1..6;
@l.&swap-each-pair;
say @l;

我把 where 子句放到 MAIN 子句中,以避免污染我的脚本的全局命名空间。在一个模块中,我们可以把它放在外面,然后重复使用。参数 Array 被标记为 is raw。这有点多余,因为无论如何,@-sigiled 的参数都是按引用调用的。通过这样做,我明确了这个子是要做一个突变器的。如果你是一个 Haskell 的爱好者,你可能要看开了。<-> 指针对所有的参数应用的 is rw。这使得我们可以用一个解构赋值来修改 @a 的元素。

where 子句 sub 使用一个好的名字,并抛出一个异常,我们会得到一个有用的错误信息与堆栈跟踪。我们必须这样做,否则就会害怕 LTA 标签

Positional with uneven elements in where clause.
  in sub check-for-even-elements at /home/dex/tmp/tmp.raku line 28
  in sub swap-each-pair at /home/dex/tmp/tmp.raku line 26
  in block <unit> at /home/dex/tmp/tmp.raku line 38

这两种语言都是后期绑定的,没有严格的类型检查。在一个庞大的代码库中,这可能会咬伤你。在这种情况下,在战略点上进行类型和值检查,并提供错误信息,实际上有助于调试,是非常有帮助的。

Raku 得到了很多功能,使模块作者的生活变得更轻松,他们想让模块用户的生活更轻松。也许有人会认为,语言设计者以前写过 CPAN 模块。

by gfldex.

comments powered by Disqus