:5hours是一个Pair,hours => 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)
虽然: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 的退化情况Map:Map具有单个键/值的不可变对象。观察:
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,因为它们在概念上做了类似的事情。