为什么不能在没有滑动的情况下将手动创建的 Pair 传递给方法?

che*_*nyf 7 raku

:5hours是一个Pairhours => 5也是一个Pair

> DateTime.now.truncated-to('day').later(:5hours)
2022-02-14T05:00:00+08:00
> :5hours.WHAT
(Pair)

> DateTime.now.truncated-to('day').later(hours => 5)
2022-02-14T05:00:00+08:00
> (hours => 5).WHAT
(Pair)
Run Code Online (Sandbox Code Playgroud)

但是,当我手动创建时Pair,它与以下签名不匹配later

> DateTime.now.truncated-to('day').later(Pair.new('hours', 5))
Cannot resolve caller later(DateTime:D: Pair:D); none of these signatures match:
    (Dateish:D: *%unit --> Dateish:D)
    (Dateish:D: @pairs, *%_)
  in block <unit> at <unknown file> line 1
Run Code Online (Sandbox Code Playgroud)

但是在参数之前使用垂直Pair就可以了:

> DateTime.now.truncated-to('day').later(|Pair.new('hours', 5))
2022-02-14T05:00:00+08:00
Run Code Online (Sandbox Code Playgroud)

:5hours那么、Pair.new('hours', 5)和 之间有什么区别hours => 5?为什么不能将手动创建的Pair诸如传递给Pair.new('hours', 5)方法later

下面这两个不是同一个东西吧?

> :5hours === Pair.new('hours', 5) === hours => 5
True
> :5hours eqv Pair.new('hours', 5) eqv hours => 5
True

> my $pair1 = Pair.new('hours', 5); dd $pair1; # Pair $pair1 = :hours(5)
> my $pair2 = :5hours; dd $pair2;              # Pair $pair2 = :hours(5)
> my $pair3 = hours => 5; dd $pair3;           # Pair $pair3 = :hours(5)
> my $pair4 = 'hours' => 5; dd $pair4;         # Pair $pair4 = :hours(5)
Run Code Online (Sandbox Code Playgroud)

Eli*_*sen 9

虽然:5hoursand 和hours => 5and:hours(5)Pair.new(hours,5)andPair.new(key => "hours", value => 5)都是创建Pair对象的不同方法,但只有前三个 是表示命名参数的语法糖

当您Pair.new("hours",5)作为参数传递时,它被视为位置参数。观察:

sub foo(*@_, *%_) {
    dd @_, %_
}

foo hours => 5;
# []
# {:hours(5)}

foo Pair.new("hours",5);
# [:hours(5)]
# {}
Run Code Online (Sandbox Code Playgroud)

至于为什么会这样呢?好吧,有时你想传递 aPair作为位置参数。如果 aPair始终被认为是命名参数,那么您将无法这样做。

至于为什么|Pair.new("hours",5)作为命名参数起作用?在|此上下文中,将给定对象(通常是 aCapture或 a Hash/ Map)展平为给定子例程的参数。在这种情况Pair下,被视为 a 的退化情况MapMap具有单个键/值的不可变对象。观察:

foo |Pair.new("hours",5);
# []
# {:hours(5)}
Run Code Online (Sandbox Code Playgroud)

嗯,可能有Associative:-)

say Pair ~~ Associative;    # True
.say for (:5hours).keys;    # hours
.say for (:5hours).values;  # 5
Run Code Online (Sandbox Code Playgroud)

最后,|在这种情况下,从技术上讲,不是Slip,而是将给定值扁平化为调用参数的语法糖。

该语法早于 a 的概念Slip(该概念于 2015 年 Great List Refactor 期间引入)。直到 2015 年很晚,|@Larry 才同意也可以用来表示 a Slip,因为它们在概念上做了类似的事情。

  • 谢谢您的详细解释! (2认同)