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



:5hoursPairhours => 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)

然而,当我手动创建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

但在Pair参数正常之前使用垂直:

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

那么:5hoursPair.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)

尽管:5hourshours => 5:hours(5)Pair.new(hours,5)Pair.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)]
# {}

至于为什么会这样?好吧,有时你想传递一个Pair作为位置参数。如果一个Pair总是被认为是一个命名的参数,你就不能这么做

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

foo |Pair.new("hours",5);
# []
# {:hours(5)}

嗯,可能是任何Associative:-(

say Pair ~~ Associative;    # True
.say for (:5hours).keys;    # hours
.say for (:5hours).values;  # 5

最后,从技术上讲,本文中的|不是Slip,而是语法糖,用于将给定值扁平化为调用的参数。

该语法早于Slip的概念(该概念于2015年大名单重构期间引入(。直到2015年很晚,@Larry才允许|也用于表示Slip,因为它们在概念上也做类似的事情。

相关内容

最新更新