我如何引用新的?

Ele*_*fee 6 higher-order-functions raku

假设我有以下代码:

my constant @suits = <Clubs Hearts Spades Diamonds>;
my constant @values = 2..14;

class Card {
    has $.suit;
    has $.value;

    # order is mnemonic of "$value of $suit", i.e. "3 of Clubs"
    multi method new($value, $suit) {
        return self.bless(:$suit, :$value);
    }
}
Run Code Online (Sandbox Code Playgroud)

它定义了一些花色和一些价值以及成为一张牌的意义。

现在,要构建一个套牌,我基本上需要将套装和值的交叉乘积并将其应用于构造函数。

这样做的天真方法当然是只用循环进行迭代:

my @deck = gather for @values X @suits -> ($v, $c) {
    take Card.new($v, $c);
}
Run Code Online (Sandbox Code Playgroud)

但这是 Raku,我们有一个cross函数,可以将函数作为可选参数!,所以我当然要这么做!

my @deck = cross(@values, @suits, :with(Card.new));
# Unexpected named argument 'with' passed
# in block <unit> at .\example.raku line 36
Run Code Online (Sandbox Code Playgroud)

……等等。那这个呢?

my @deck = cross(@values, @suits):with(Card.new);
# Unexpected named argument 'with' passed
# in block <unit> at .\example.raku line 36
Run Code Online (Sandbox Code Playgroud)

依然没有。可以参考吗?

my @deck = cross(@values, @suits):with(&Card.new);
# ===SORRY!=== Error while compiling D:\Code\Raku/.\example.raku
# Illegally post-declared type:
#    Card used at line 36
Run Code Online (Sandbox Code Playgroud)

我在某处读到我可以将函数转换为中缀运算符 []

my @deck = cross(@values, @suits):with([Card.new]);
# Unexpected named argument 'with' passed
# in block <unit> at .\example.raku line 36
Run Code Online (Sandbox Code Playgroud)

那也行不通。

如果类应该只是模块,那么我不应该能够传递函数引用吗?

还有为什么说'with'是出乎意料的?如果我的直觉是正确的,它实际上抱怨的是输入的类型,而不是命名参数。

Eli*_*sen 8

错误信息确实令人困惑。

:with参数需要一个 Callable。 Card.new不是一个Callable。如果你把它写成:with( { Card.new($^number, $^suit) } ),它似乎可以工作。

请注意,我没有使用$^value, $^suit,因为它们按字母顺序排列不同,因此会以错误的顺序生成值。有关语法的更多信息,请参阅^ twigil

该错误LTA,使得它稍微好一点。

回到您的问题:您可以找到Card.new^find_method. 但是,这将不起作用,因为Card.new实际上期望3 个参数:调用者(又名self$value$suit. 而cross函数只会传递值和花色。