is Mu
虽然 Mu
是 Raku 类层次结构的根,但 Any
是用作新类的默认基类的类,也是大多数内置类的基类。
由于 Raku 故意混淆了项目和单元素列表,因此 Any
中的大多数方法也存在于类 List
上,并强制转换为 List 或类似列表的类型。
方法§
方法 ACCEPTS§
multi method ACCEPTS(Any: Mu )
用法
EXPR.ACCEPTS(EXPR);
如果 $other === self
(即它检查对象标识),则返回 True
。
许多内置类型会覆盖此方法以进行更具体的比较。
方法 any§
method any(--> Junction)
将调用者解释为列表,并从中创建一个 any-Junction
。
say so 2 == <1 2 3>.any; # OUTPUT: «True»say so 5 == <1 2 3>.any; # OUTPUT: «False»
方法 all§
method all(--> Junction)
将调用者解释为列表,并从中创建一个 all-Junction
。
say so 1 < <2 3 4>.all; # OUTPUT: «True»say so 3 < <2 3 4>.all; # OUTPUT: «False»
方法 one§
method one(--> Junction)
将调用者解释为列表,并从中创建一个 one-Junction
。
say so 1 == (1, 2, 3).one; # OUTPUT: «True»say so 1 == (1, 2, 1).one; # OUTPUT: «False»
方法 none§
method none(--> Junction)
将调用者解释为列表,并从中创建一个 none-Junction
。
say so 1 == (1, 2, 3).none; # OUTPUT: «False»say so 4 == (1, 2, 3).none; # OUTPUT: «True»
方法 list§
multi method list(Any:)multi method list(Any \SELF:)
say 42.list.^name; # OUTPUT: «List»say 42.list.elems; # OUTPUT: «1»
Any
的子类可以选择返回任何核心类型,该类型从 .list
执行 Positional
角色。使用 .List
强制专门转换为 List
。
@
也可以用作列表或 Positional
上下文化器
my = $[1,2,3];say .raku; # OUTPUT: «$[1, 2, 3]»my = @;say .^name; # OUTPUT: «Array»
在第一种情况下,列表是项目化的。@
作为前缀通过调用 .list
并将其转换为 Array
将初始标量置于列表上下文中。
方法 push§
multi method push(Any \SELF: |values --> Positional)
push 方法为未定义的调用者定义,并允许将未定义的值自动转换为空 Array
,除非未定义的值已经实现了 Positional
。然后,提供的参数将被推入新创建的 Array 中。
my ;say <a>; # OUTPUT: «(Any)» <-- Undefined<a>.push(1); # .push on Anysay ; # OUTPUT: «{a => [1]}» <-- Note the Array
例程 reverse§
multi reverse(* --> Seq)multi method reverse(List: --> Seq)
返回一个 Seq
,其中包含相同元素,但顺序相反。
请注意,reverse
始终是指反转列表的元素;要反转字符串中的字符,请使用 flip。
示例
say <hello world!>.reverse; # OUTPUT: «(world! hello)»say reverse ^10; # OUTPUT: «(9 8 7 6 5 4 3 2 1 0)»
方法 sort§
multi method sort()multi method sort()
使用 cmp 或给定的代码对象对可迭代对象进行排序,并返回一个新的 Seq
。可选地,将 Callable
作为位置参数,指定如何排序。
示例
say <b c a>.sort; # OUTPUT: «(a b c)»say 'bca'.comb.sort.join; # OUTPUT: «abc»say 'bca'.comb.sort().join; # OUTPUT: «cba»say '231'.comb.sort(:«<=>»).join; # OUTPUT: «123»sub by-character-countsay <Let us impart what we have seen tonight unto young Hamlet>.sort();# OUTPUT: «(us we Let what have seen unto young impart Hamlet tonight)»
例程 map§
multi method map(\SELF: )multi map(, +values)
map
将迭代调用者,并根据每次调用的调用者中的代码对象的位数参数数量应用代码对象。代码对象的返回值将成为返回的 Seq
的元素。
:$label
和 :$item
仅在内部有用,因为 for
循环会被转换为 map
。:$label
使用一个现有的 Label
来标记 .map
的循环,而 :$item
控制迭代是发生在 (SELF,)
上(如果设置了 :$item
)还是 SELF
上。
在 sub
形式中,它将把 code
块应用于 values
,这些 values
将用作调用者。
带有 |c
、Iterable:D \iterable
和 Hash:D \hash
作为签名的形式将以 X::Cannot::Map
失败,主要用于捕获常见的陷阱。
在一个已经被下沉的 for
语句中,由 map 创建的 Seq
也会下沉。
say gather for 1# OUTPUT: «(0 1 2)»
在这种情况下,gather
会下沉 for
语句,下沉 Seq
的结果将是对其元素进行迭代,并对它们调用 .take
。
方法 deepmap§
method deepmap( --> List) is nodal
deepmap
将把 &block
应用于每个元素,并返回一个新的 List
,其中包含 &block
的返回值,除非该元素具有 Iterable
角色。对于这些元素,deepmap 将递归地下降到子列表中。
say [[1,2,3],[[4,5],6,7]].deepmap(* + 1);# OUTPUT: «[[2 3 4] [[5 6] 7 8]]»
对于 Associative
,它将应用于其值。
.deepmap( *.flip ).say# OUTPUT: «{a => (laer tsil), this => gniht, what => si}»
方法 duckmap§
method duckmap() is rw is nodal
duckmap
将把 &block
应用于每个以这样一种方式表现的元素,即 &block
可以被应用。如果失败,它将尽可能递归地下降,否则将返回该项而不进行任何转换。如果对象是 Associative
,它将作用于值。
<a b c d e f g>.duckmap(-> where <c d e>.any ).say;# OUTPUT: «(a b C D E f g)»(('d', 'e'), 'f').duckmap(-> where <e f>.any ).say;# OUTPUT: «((d E) F)».duckmap(-> where <e f>.any ).say;# OUTPUT: «{first => (d E), second => F}»
在第一种情况下,它被应用于 c
、d
和 e
,它们是满足块({ .uc }
)应用条件的元素;其余元素按原样返回。
在第二种情况下,第一个元素是一个不满足条件的列表,因此它被访问;该扁平列表的行为将与第一个列表相同。在这种情况下
say [[1,2,3],[[4,5],6,7]].duckmap( *² ); # OUTPUT: «[9 9]»
只要像数字一样表现,你就可以对任何东西进行平方。在这种情况下,有两个包含 3 个元素的数组;这些数组将被转换为数字 3 并进行平方。在下一种情况下,然而
say [[1,2,3],[[4,5],6.1,7.2]].duckmap( -> Rat );# OUTPUT: «[[1 2 3] [[4 5] 37.21 51.84]]»
3 个元素的列表不是 Rat
,因此它递归地下降,但最终只对那些像 Rat
一样行走(或爬行,视情况而定)的元素应用操作。
虽然在表面上(和名称上),duckmap
可能看起来类似于 deepmap
,但后者无论项目的类型如何,都会递归地应用。
方法 nodemap§
method nodemap( --> List) is nodal
nodemap
将把 &block
应用于每个元素,并返回一个新的 List
,其中包含 &block
的返回值。与 deepmap 相反,如果它发现具有 Iterable
角色的元素,它不会递归地下降到子列表中。
say [[1,2,3], [[4,5],6,7], 7].nodemap(*+1);# OUTPUT: «(4, 4, 8)»say [[2, 3], [4, [5, 6]]]».nodemap(*+1)# OUTPUT: «((3 4) (5 3))»
如果我们使用 map 而不是 nodemap
,上面的示例将产生完全相同的结果。两者之间的区别在于 map 会将 Slip
展平,而 nodemap
不会。
say [[2,3], [[4,5],6,7], 7].nodemap();# OUTPUT: «(() () 7)»say [[2,3], [[4,5],6,7], 7].map();# OUTPUT: «(7)»
当应用于 Associative
时,它将作用于值。
.nodemap( *.flip ).say;# OUTPUT: «{this => gniht, what => si}»
方法 flat§
method flat() is nodal
将调用者解释为一个列表,将 非容器化 Iterable
展平为一个扁平列表,并返回该列表。请记住,Map
和 Hash
类型是 Iterable
,因此将被展平为成对的列表。
say ((1, 2), (3), %(:42a)); # OUTPUT: «((1 2) 3 {a => 42})»say ((1, 2), (3), %(:42a)).flat; # OUTPUT: «(1 2 3 a => 42)»
请注意,Array
默认情况下会容器化其元素,因此 flat
不会展平它们。你可以使用
超方法调用 对所有内部 Iterable
调用 .List
方法,从而将它们去容器化,以便 flat
可以展平它们。
say [[1, 2, 3], [(4, 5), 6, 7]] .flat; # OUTPUT: «([1 2 3] [(4 5) 6 7])»say [[1, 2, 3], [(4, 5), 6, 7]]».List.flat; # OUTPUT: «(1 2 3 4 5 6 7)»
有关更多微调选项,请参阅 deepmap、duckmap 和 签名解构
方法 eager§
method eager() is nodal
将调用者解释为一个 List
,对其进行急切求值,并返回该 List
。
my = 1..5;say ; # OUTPUT: «1..5»say .eager; # OUTPUT: «(1 2 3 4 5)»
方法 elems§
multi method elems(Any: --> 1)multi method elems(Any:)
将调用者解释为一个列表,并返回列表中元素的数量。
say 42.elems; # OUTPUT: «1»say <a b c>.elems; # OUTPUT: «3»say Whatever.elems ; # OUTPUT: «1»
它也会为类返回 1。
方法 end§
multi method end(Any: --> 0)multi method end(Any:)
将调用者解释为一个列表,并返回该列表的最后一个索引。
say 6.end; # OUTPUT: «0»say <a b c>.end; # OUTPUT: «2»
方法 pairup§
multi method pairup(Any:)multi method pairup(Any:)
如果调用者是一个类型对象,则返回一个空的 Seq
Range.pairup.say; # OUTPUT: «()»
将调用者解释为一个列表,并从中构建一个 Pair
列表,与分配给 Hash
的方式相同。也就是说,它获取两个连续的元素并从中构建一个对,除非键位置的项目本身就是一个对(在这种情况下,该对将被传递,并且下一个列表项(如果有)被认为是一个键)。它返回一个 Seq
的 Pair
。
say (a => 1, 'b', 'c').pairup.raku; # OUTPUT: «(:a(1), :b("c")).Seq»
子项§
multi item(\x)multi item(|c)multi item(Mu )
强制给定对象在项目上下文中求值,并返回其值。
say item([1,2,3]).raku; # OUTPUT: «$[1, 2, 3]»say item( %( apple => 10 ) ).raku; # OUTPUT: «${:apple(10)}»say item("abc").raku; # OUTPUT: «"abc"»
您也可以使用 $
作为项目上下文化器。
say $[1,2,3].raku; # OUTPUT: «$[1, 2, 3]»say $("abc").raku; # OUTPUT: «"abc"»
方法 Array§
method Array(--> Array) is nodal
将调用者强制转换为 Array
。
方法 List§
method List(--> List) is nodal
方法 serial§
multi method serial()
此方法是 Rakudo 特定的,未包含在 Raku 规范中。
该方法返回对实例本身的自引用。
my ; # defaults to Anysay .serial.^name; # OUTPUT: «Any»say .^name; # OUTPUT: «Any»my = 'food';.serial.say; # OUTPUT: «food»
这显然是一个无操作,如上面的第三个示例所示。但是,在 HyperSeq
和 RaceSeq
中,它返回一个序列化 Seq
,因此可以将其视为 hyper/race
方法的相反。因此,它确保我们处于串行列表处理模式,而不是这些方法的自动线程模式。
方法 Hash§
multi method Hash( --> Hash)
将调用者强制转换为 Hash
。
方法 hash§
multi method hash(Any:)multi method hash(Any:)
当在类型对象上调用时,返回一个空的 Hash
。在实例上,它等效于将调用者分配给一个 %-
标记的变量并返回它。
Any
的子类可以选择返回任何核心类型,该类型从 .hash
执行 Associative
角色。使用 .Hash
特别强制转换为 Hash
。
my ; # $d is Anysay .hash; # OUTPUT: {}my is Map = a => 42, b => 666;say .hash; # OUTPUT: «Map.new((a => 42, b => 666))»say .Hash; # OUTPUT: «{a => 42, b => 666}»
方法 Slip§
method Slip(--> Slip) is nodal
将调用者强制转换为 Slip
。
方法 Map§
method Map(--> Map) is nodal
将调用者强制转换为 Map
。
方法 Seq§
method Seq() is nodal
将调用者强制转换为 Seq
。
方法 Bag§
method Bag(--> Bag) is nodal
将调用者强制转换为 Bag
,其中 Positional
被视为值的列表。
方法 BagHash§
method BagHash(--> BagHash) is nodal
将调用者强制转换为 BagHash
,其中 Positional
被视为值的列表。
方法 Set§
method Set(--> Set) is nodal
将调用者强制转换为 Set
,其中 Positional
被视为值列表。
方法 SetHash§
method SetHash(--> SetHash) is nodal
将调用者强制转换为 SetHash
,其中 Positional
被视为值列表。
方法 Mix§
method Mix(--> Mix) is nodal
将调用者强制转换为 Mix
,其中 Positional
被视为值列表。
方法 MixHash§
method MixHash(--> MixHash) is nodal
将调用者强制转换为 MixHash
,其中 Positional
被视为值列表。
方法 Supply§
method Supply(--> Supply) is nodal
首先,它通过应用调用者的 .list
方法将其强制转换为 list
,然后强制转换为 Supply
。
例程 min§
multi method min(?, :, :, :, : )multi min(+args, :, :, :, :, :)
将调用者强制转换为 Iterable
并使用 cmp 语义返回最小元素;对于 Map
和 Hash
,它返回具有最低值的 Pair
。
可以向 method
形式提供一个 Callable
位置参数。如果该 Callable
接受单个参数,则它将用于在进行比较之前转换要排序的值。原始值仍然是 min
返回的值。
如果该 Callable
接受两个参数,则它将用作比较器,而不是 cmp
。
在 sub
形式中,调用者作为参数传递,任何 Callable
都必须使用命名参数 :by
指定。
say (1,7,3).min(); # OUTPUT: «1»say (1,7,3).min(); # OUTPUT: «7»say min(1,7,3); # OUTPUT: «1»say min(1,7,3,:by( )); # OUTPUT: «7»min( %(a => 3, b=> 7 ) ).say ; # OUTPUT: «a => 3»
从 2023.08 Rakudo 编译器版本开始,可以指定额外的命名参数以获取与最低值相关的所有可能信息。只要指定了任何这些命名参数,返回值始终为 List
。
:k
返回一个包含找到的最低值的索引的 List
。
:v
返回一个包含找到的最低值的实际值的 List
。对于 Map
或 Hash
,这些将是 Pair
。
:kv
返回一个包含索引和值的交替排列的 List
。
:p
返回一个包含 Pair
的 List
,其中键是索引值,值是实际的最低值(对于 Map
或 Hash
,这将是一个 Pair
)。
say <a b c a>.min(:k); # OUTPUT:«(0 3)»say <a b c a>.min(:v); # OUTPUT:«(a a)»say <a b c a>.min(:kv); # OUTPUT:«(0 a 3 a)»say <a b c a>.min(:p); # OUTPUT:«(0 => a 3 => a)»
例程 max§
multi method max(?, :, :, :, : )multi max(+args, :, :, :, :, :)
max
方法/例程的接口与 min 的接口相同。但它将返回最高值,而不是最低值,这很明显。
say (1,7,3).max(); # OUTPUT: «7»say (1,7,3).max(); # OUTPUT: «1»say max(1,7,3,:by( )); # OUTPUT: «1»say max(1,7,3); # OUTPUT: «7»max( %(a => 'B', b=> 'C' ) ).say; # OUTPUT: «b => C»
从 2023.08 Rakudo 编译器版本开始
say <a b c c>.max(:k); # OUTPUT:«(2 3)»say <a b c c>.max(:v); # OUTPUT:«(c c)»say <a b c c>.max(:kv); # OUTPUT:«(2 c 3 c)»say <a b c c>.max(:p); # OUTPUT:«(2 => c 3 => c)»
例程 minmax§
multi method minmax()multi method minmax()multi minmax(+args, :!)multi minmax(+args)
返回从最小元素到最大元素的 Range
。
如果提供了 Callable
位置参数,则每个值都会传递到过滤器中,并且会比较其返回值,而不是原始值。原始值仍然用于返回的 Range
中。
在 sub
形式中,调用者作为参数传递,并且可以使用命名参数 :by
指定比较 Callable
。
say (1,7,3).minmax(); # OUTPUT:«1..7»say (1,7,3).minmax(); # OUTPUT:«7..1»say minmax(1,7,3); # OUTPUT: «1..7»say minmax(1,7,3,:by( -* )); # OUTPUT: «7..1»
方法 minpairs§
multi method minpairs(Any:)
调用 .pairs
并返回一个包含所有最小值的 Pair 的 Seq
,由 cmp
运算符 判断。
<a b c a b c>.minpairs.raku.put; # OUTPUT: «(0 => "a", 3 => "a").Seq»%(:42a, :75b).minpairs.raku.put; # OUTPUT: «(:a(42),).Seq»
方法 maxpairs§
multi method maxpairs(Any:)
调用 .pairs
并返回一个包含所有最大值的 Pair 的 Seq
,由 cmp
运算符 判断。
<a b c a b c>.maxpairs.raku.put; # OUTPUT: «(2 => "c", 5 => "c").Seq»%(:42a, :75b).maxpairs.raku.put; # OUTPUT: «(:b(75),).Seq»
方法 keys§
multi method keys(Any: --> List)multi method keys(Any: --> List)
对于已定义的 Any
,在调用 list
后返回其 键,否则调用 list
并返回它。
my = Set(<Þor Oðin Freija>);say .keys; # OUTPUT: «(Þor Oðin Freija)»
另请参阅 List.keys
。
尝试对类执行相同的操作将返回一个空列表,因为大多数类实际上没有键。
方法 flatmap§
method flatmap(, :)
便捷方法,类似于 .map(&block)
.flat
。
方法 roll§
multi method roll(--> Any)multi method roll( --> Seq)
通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.roll
。
my Mix = ("þ" xx 3, "ð" xx 4, "ß" xx 5).Mix;say .roll; # OUTPUT: «ð»say .roll(5); # OUTPUT: «(ß ß þ ß þ)»
在这种情况下,$m
被转换为列表,然后在其上滚动一个(加权的)骰子。有关更多信息,请参阅 List.roll
。
方法 iterator§
multi method iterator(Any:)
将对象转换为列表后,将其作为迭代器返回。这是 for
语句调用的函数。
.say for 3; # OUTPUT: «3»
大多数子类重新定义此方法以进行优化,因此,实际上迭代的类型主要是那些实际上使用此实现的类型。
方法 pick§
multi method pick(--> Any)multi method pick( --> Seq)
通过应用其 .list
方法将调用者强制转换为 List
,并在其上使用 List.pick
。
my Range = 'α'..'ω';say .pick(3); # OUTPUT: «(β α σ)»
例程 skip§
multi method skip()multi method skip(Whatever)multi method skip(Callable )multi method skip(Int() )multi method skip(, )
从 1 项列表的迭代器创建 Seq
,并在其上使用 Seq.skip
,请检查该文档以了解实际用例;调用不带参数的 skip
等效于 skip(1)
。
multi skip(\skipper, +values)
从 Rakudo 编译器 2022.07 版本开始,还存在 skip
的“sub”版本。它**必须**将跳过说明符作为第一个参数。其余参数将转换为 Seq
,然后在其上调用 skip
方法。
方法 are§
multi method are(Any:)multi method are(Any: Any )
Rakudo 编译器 2022.02 版本提供的无参数版本。带类型参数的版本在 6.e 语言版本中(Rakudo 编译器 2024.05+ 中存在早期实现)。
如果在没有参数的情况下调用,则返回最严格的类型(或角色),列表中的**所有**元素都将与之智能匹配。在空列表上返回 Nil
。
say (1,2,3).are; # OUTPUT: «(Int)»say <a b c>.are; # OUTPUT: «(Str)»say <42 666>.are; # OUTPUT: «(IntStr)»say (42,666e0).are; # OUTPUT: «(Real)»say (42,i).are; # OUTPUT: «(Numeric)»say ("a",42,3.14).are; # OUTPUT: «(Cool)»say ().are; # OUTPUT: «Nil»
标量值被解释为单个元素列表。
say 42.are; # OUTPUT: «(Int)»say Int.are; # OUTPUT: «(Int)»
哈希将被解释为一对列表,因此将始终生成 Pair
类型对象。使用 .keys
或 .values
方法获取哈希键或值的严格类型。
my = a => 42, b => "bar";say .keys.are; # OUTPUT: «(Str)»say .values.are; # OUTPUT: «(Cool)»
如果带类型参数调用,则将检查调用者中的所有类型是否与给定类型智能匹配。如果是,则返回 True
。如果任何智能匹配失败,则返回 Failure
。
say (1,2,3).are(Int); # OUTPUT: «True»say <a b c>.are(Str); # OUTPUT: «True»say <42 666>.are(Int); # OUTPUT: «True»say <42 666>.are(Str); # OUTPUT: «True»say (42,666e0).are(Real); # OUTPUT: «True»say (42,i).are(Numeric); # OUTPUT: «True»say ("a",42,3.14).are(Cool); # OUTPUT: «True»say ().are; # OUTPUT: «True»Int.are(Str); # OUTPUT: «Expected 'Str' but got 'Int'»(1,2,3).are(Str); # OUTPUT: «Expected 'Str' but got 'Int' in element 0»
方法 prepend§
multi method prepend(Any: --> Array)multi method prepend(Any: --> Array)
在空变量上不带参数调用时,它将其初始化为一个空的 Array
;如果带参数调用,它将创建一个数组,然后在其上应用 Array.prepend
。
my ;say .prepend; # OUTPUT: «[]»say ; # OUTPUT: «[]»my ;say .prepend(1,2,3); # OUTPUT: «[1 2 3]»
方法 unshift§
multi method unshift(Any: --> Array)multi method unshift(Any: --> Array)
将 Any
变量初始化为空的 Array
,并在其上调用 Array.unshift
。
my ;say .unshift; # OUTPUT: «[]»say ; # OUTPUT: «[]»my ;say .unshift([1,2,3]); # OUTPUT: «[[1 2 3]]»
routine first§
multi method first(Bool )multi method first(Regex , :, *)multi method first(Callable , :, * is copy)multi method first(Mu , :, *)multi method first(:, *)multi first(Bool , |)multi first(Mu , +values, *)
通常,通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.first
。
但是,这是一个具有不同签名的多方法,它们使用(略微)不同的行为实现,尽管将其用作子例程等效于将其用作具有第二个参数作为对象的方法。
首先,使用 Bool
作为参数将始终返回 Failure
。使用 $test
的形式将返回与之智能匹配的第一个元素,如果使用 :end
,则从末尾开始。
say (3..33).first; # OUTPUT: «3»say (3..33).first(:end); # OUTPUT: «33»say (⅓,⅔…30).first( 0xF ); # OUTPUT: «15»say first 0xF, (⅓,⅔…30); # OUTPUT: «15»say (3..33).first( /\d\d/ ); # OUTPUT: «10»
第三和第四个示例使用 Mu $test
形式,它们智能匹配并返回第一个匹配的元素。最后一个示例使用正则表达式作为测试,用于表示两位数,因此第一个满足该条件的数字是 10。最后一种形式使用 Callable
多方法。
say (⅓,⅔…30).first( * %% 11, :end, :kv ); # OUTPUT: «(65 22)»
此外,对第一个元素的搜索将从 :end
开始,并返回一个列表中的键/值集;在这种情况下,键 只是它在 Seq
中所占的位置。:kv
参数(它是上面定义中 %a
参数的一部分)修改了 first
的返回值,将其提供为键和值的扁平化列表;对于列表对象,键始终是索引。
从 6.d 版本开始,测试也可以是 Junction
say (⅓,⅔…30).first( 3 | 33, :kv ); # OUTPUT: «(8 3)»
method unique§
multi method unique()multi method unique( :!, :! )multi method unique( :! )multi method unique( :! )
创建一个唯一元素的序列,这些元素可以是对象本身的元素,也可以是作为 sub
调用时 values
中的元素。
<1 2 2 3 3 3>.unique.say; # OUTPUT: «(1 2 3)»say unique <1 2 2 3 3 3>; # OUTPUT: «(1 2 3)»
:as
和 :with
参数接收函数,这些函数用于在检查相等性之前转换项目,以及用于检查相等性,因为默认情况下使用 ===
运算符。
("1", 1, "1 ", 2).unique( as => Int, with => &[==] ).say; # OUTPUT: «(1 2)»
请参阅 unique
,以获取使用其子形式的其他示例。
method repeated§
multi method repeated()multi method repeated( :!, :! )multi method repeated( :! )multi method repeated( :! )
与 unique
类似,在 values
(作为例程)或对象中查找重复元素,使用 :as
关联参数作为规范化函数,使用 :with
作为相等性函数。
<1 -1 2 -2 3>.repeated(:as(),:with(&[==])).say; # OUTPUT: «(-1 -2)»(3+3i, 3+2i, 2+1i).repeated(as => *.re).say; # OUTPUT: «(3+2i)»
它返回规范化之前的最后一个重复元素,如上面的示例所示。请参阅 repeated
,以获取使用其子形式的更多示例。
method squish§
multi method squish( :!, : = &[===] )multi method squish( : = &[===] )
类似于 .repeated
,返回连续相等元素序列的第一个元素的序列,如果存在,则通过函数 :as
进行规范化,并使用 :with
参数或默认的 ===
作为相等性运算符。
"aabbccddaa".comb.squish.say; # OUTPUT: «(a b c d a)»"aABbccdDaa".comb.squish( :as() ).say; # OUTPUT: «(a B c d a)»(3+2i,3+3i,4+0i).squish( as => *.re, with => &[==]).put; # OUTPUT: «3+2i 4+0i»
如最后一个示例所示,序列可以包含单个元素。请参阅 squish
,以获取其他 sub
示例。
method permutations§
method permutations(|c)
通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.permutations
。
say <a b c>.permutations;# OUTPUT: «((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))»say set(1,2).permutations;# OUTPUT: «((2 => True 1 => True) (1 => True 2 => True))»
对具有单个元素或没有元素的数据结构的排列将返回一个列表,该列表包含一个空列表或一个包含单个元素的列表。
say 1.permutations; # OUTPUT: «((1))»
method join§
method join( = '') is nodal
通过调用 self.list
将对象转换为列表,并在列表上调用 .join
。可以接受一个分隔符,默认情况下为空字符串。
(1..3).join.say; # OUTPUT: «123»<a b c>.join("❧").put; # OUTPUT: «a❧b❧c»
routine categorize§
multi method categorize()multi method categorize(Whatever)multi method categorize(, :!, :)multi method categorize(, :)multi categorize(, +items, :!, * )multi categorize(, +items, * )
第一种形式将始终失败。第二种形式根据给定对象的标识进行分类,这通常只有与 :&as
参数结合使用时才有意义。
在最简单的形式中,它使用一个 $test
,其结果将用作键;键的值将是产生该键作为测试结果的元素的数组。
say (1..13).categorize( * %% 3);say categorize( * %% 3, 1..13)# OUTPUT: «{False => [1 2 4 5 7 8 10 11 13], True => [3 6 9 12]}»
:as
参数将在分类之前进行规范化。
say categorize( * %% 3, -5..5, as => )# OUTPUT: «{False => [5 4 2 1 1 2 4 5], True => [3 0 3]}»
$into
关联参数可用于将结果放入其中,而不是返回新的 Hash
。
my ;my = (2002..2009).map( );.categorize( *.is-leap-year , into => );say# OUTPUT:# «{ False# => [2002-01-01 2003-01-01 2005-01-01 2006-01-01 2007-01-01 2009-01-01],# True => [2004-01-01 2008-01-01]}»
用于分类的函数可以返回一个数组,指示其参数可以放入的所有可能的箱子。
sub divisible-by( Int --> Array(Seq) )say (3..13).categorize( );# OUTPUT:# «{2 => [4 6 8 10 12], 3 => [3 6 9 12], 5 => [5 10], 7 => [7]}»
在这种情况下,范围内的每个数字都被分类到尽可能多的箱子中。
在 Rakudo 编译器版本 2023.02 中添加了对使用 Whatever
作为测试的支持。
routine classify§
multi method classify()multi method classify(Whatever)multi method classify(, :!, :)multi method classify(, :)multi classify(, +items, :!, * )multi classify(, +items, * )
第一种形式将始终失败。第二种形式根据给定对象的标识进行分类,这通常只有与 :&as
参数结合使用时才有意义。
其余部分包括一个 $test
参数,它是一个函数,将为每个输入返回一个标量;这些将用作哈希的键,其值将是包含对测试函数输出该键的元素的数组。
my = (2003..2008).map( );.classify( *.is-leap-year , into => my );say ;# OUTPUT: «{False => [2003-01-01 2005-01-01 2006-01-01 2007-01-01],# True => [2004-01-01 2008-01-01]}»
类似于 .categorize
,元素可以通过 :as
参数传递的 Callable
进行规范化,并且可以使用 :into
命名参数传递一个 Hash
,结果将被分类到其中;在上面的示例中,它是动态定义的。
从 6.d 版本开始,.classify
也将适用于 Junction
。
在 Rakudo 编译器版本 2023.02 中添加了对使用 Whatever
作为测试的支持。
routine reduce§
multi method reduce(Any: & --> Nil)multi method reduce(Any: )multi reduce (, +list)
此例程通过应用二元子例程来组合列表状对象中的元素,并产生单个结果。它将它的参数(或子形式的第一个参数)作为运算符应用于对象中的所有元素(或子形式的第二个参数),产生单个结果。子例程必须是 中缀运算符 或接受两个位置参数。当使用中缀运算符时,我们必须提供其子例程版本的代码对象,即运算符类别,后跟冒号,然后是包含构成运算符的符号的列表引用构造(例如,infix:<+>
)。参见 运算符。
say (1..4).reduce(:<+>); # OUTPUT: «10»say reduce :<+>, 1..4; # OUTPUT: «10»say reduce , 1..4; # OUTPUT: «1»sub hyphenate(Str \a, Str \b)say reduce , 'a'..'c'; # OUTPUT: «a-b-c»
应用于类时,例程将始终返回 Nil
。
say Range.reduce(:<+>); # OUTPUT: «Nil»say Str.reduce(:<~>); # OUTPUT: «Nil»
参见 List.reduce 以获得更详细的讨论。
routine produce§
multi method produce(Any: & --> Nil)multi method produce(Any: )multi produce (, +list)
这类似于 reduce
,但返回一个包含累积值的列表,而不是单个结果。
<10 5 3>.reduce( &[*] ).say ; # OUTPUT: «150»<10 5 3>.produce( &[*] ).say; # OUTPUT: «(10 50 150)»
生成的列表的最后一个元素将是 .reduce
方法产生的输出。
如果它是一个类,它将简单地返回 Nil。
method pairs§
multi method pairs(Any:)multi method pairs(Any:)
如果调用者是类型对象,则返回一个空的 List
say Num.pairs; # OUTPUT: «()»
对于值对象,它通过 list
方法将调用者转换为 List
,并返回 List.pairs 对其的结果。
<1 2 2 3 3 3>.Bag.pairs.say;# OUTPUT: «(1 => 1 3 => 3 2 => 2)»
在这种情况下,包中的每个元素(带权重)都被转换为一个对。
method antipairs§
multi method antipairs(Any:)multi method antipairs(Any:)
如果调用者是类型对象,则返回一个空的 List
Range.antipairs.say; # OUTPUT: «()»
如果它是一个值对象,它将在将其转换为一对列表后返回反转的对列表;值将成为键,反之亦然。
%(s => 1, t=> 2, u => 3).antipairs.say ;# OUTPUT: «(2 => t 1 => s 3 => u)»
method invert§
multi method invert(Any:)multi method invert(Any:)
应用于类型对象将返回一个空列表;应用于对象将将其转换为列表并应用 List.invert
到它,也就是说,在每个对中交换键和值。生成的列表需要是一个 Pair
列表。
"aaabbcccc".comb.Bag.invert.say; # OUTPUT: «(4 => c 3 => a 2 => b)»
在这种情况下,Bag
可以转换为 Pair
列表。如果将对象转换为列表的结果不是一对列表,则该方法将失败。
routine kv§
multi method kv(Any:)multi method kv(Any:)multi kv()
如果调用者是类型对象,则返回一个空的 List
Sub.kv.say ;# OUTPUT: «()»
它对调用者调用 list
以获取值对象,并返回 List.kv 对其的结果,作为一个列表,其中键和值将被排序并相邻
<1 2 3>.kv.say; # OUTPUT: «(0 1 1 2 2 3)»
在 Positional
的情况下,索引将被视为键。
method toggle§
method toggle(Any: * where .all ~~ Callable, Bool : --> Seq)
迭代 调用者,产生一个 Seq
,切换接收到的值是否根据 @conditions
中调用 Callables
的结果在结果中传播。
say (1..15).toggle(* < 5, * > 10, * < 15); # OUTPUT: «(1 2 3 4 11 12 13 14)»say (1..15).toggle(:off, * > 2, * < 5, * > 10, * < 15); # OUTPUT: «(3 4 11 12 13 14)»
想象一个开关,它要么打开要么关闭(True
或 False
),如果它打开,则会产生值。默认情况下,该开关的初始状态为“打开”位置,除非 :$off
设置为真值,在这种情况下,初始状态将为“关闭”。
从 @conditions
的开头获取一个 Callable
(如果有的话),它将成为当前测试器。原始序列中的每个值都通过调用测试器 Callable
并传入该值来进行测试。我们想象中的开关状态设置为测试器的返回值:如果返回值为真,则将开关设置为“开”,否则设置为“关”。
每当开关切换(即从“关”切换到“开”或从“开”切换到“关”)时,当前测试器 Callable
将被 @conditions
中的下一个 Callable
替换(如果有),该测试器将用于测试任何进一步的值。如果没有更多测试器 Callable
可用,则开关将保持其当前状态,直到迭代结束。
# our original sequence of elements:say list ^10; # OUTPUT: «(0 1 2 3 4 5 6 7 8 9)»# toggled result:say ^10 .toggle: * < 4, * %% 2, ; # OUTPUT: «(0 1 2 3 6 7)»# First tester Callable is `* < 4` and initial state of switch is "on".# As we iterate over our original sequence:# 0 => 0 < 4 === True switch is on, value gets into result, switch is# toggled, so we keep using the same Callable:# 1 => 1 < 4 === True same# 2 => 2 < 4 === True same# 3 => 3 < 4 === True same# 4 => 4 < 4 === False switch is now off, "4" does not make it into the# result. In addition, our switch got toggled, so# we're switching to the next tester Callable# 5 => 5 %% 2 === False switch is still off, keep trying to find a value# 6 => 6 %% 2 === True switch is now on, take "6" into result. The switch# toggled, so we'll use the next tester Callable# 7 => is-prime(7) === True switch is still on, take value and keep going# 8 => is-prime(8) === False switch is now off, "8" does not make it into# the result. The switch got toggled, but we# don't have any more tester Callables, so it# will remain off for the rest of the sequence.
由于开关状态的切换会加载下一个测试器 Callable
,因此将 :$off
设置为 True
值会影响第一个测试器被丢弃的时间。
# our original sequence of elements:say <0 1 2>; # OUTPUT: «(0 1 2)»# toggled result:say <0 1 2>.toggle: * > 1; # OUTPUT: «()»# First tester Callable is `* > 1` and initial state of switch is "on".# As we iterate over our original sequence:# 0 => 0 > 1 === False switch is off, "0" does not make it into result.# In addition, switch got toggled, so we change the# tester Callable, and since we don't have any more# of them, the switch will remain "off" until the end
当使用 :off
时,行为会发生变化。
# our original sequence of elements:say <0 1 2>; # OUTPUT: «(0 1 2)»# toggled result:say <0 1 2>.toggle: :off, * > 1; # OUTPUT: «(2)»# First tester Callable is `* > 1` and initial state of switch is "off".# As we iterate over our original sequence:# 0 => 0 > 1 === False switch is off, "0" does not make it into result.# The switch did NOT get toggled this time, so we# keep using our current tester Callable# 1 => 1 > 1 === False same# 2 => 2 > 1 === True switch is on, "2" makes it into the result
例程头部§
multi method head(Any:) is rawmulti method head(Any: Callable )multi method head(Any: )
返回对象中的第一个元素,或者如果使用了 $n
,则返回前 $n
个元素。
"aaabbc".comb.head.put; # OUTPUT: «a»say ^10 .head(5); # OUTPUT: «(0 1 2 3 4)»say ^∞ .head(5); # OUTPUT: «(0 1 2 3 4)»say ^10 .head; # OUTPUT: «0»say ^∞ .head; # OUTPUT: «0»
在前两种情况下,结果不同,因为 Mix
中没有定义的顺序。在其他情况下,它返回一个 Seq
。可以使用 Callable
返回除最后一个元素之外的所有元素。
say (^10).head( * - 3 );# OUTPUT: «(0 1 2 3 4 5 6)»
从 Rakudo 编译器的 2022.07 版本开始,还有一个 head
的“子”版本。
multi head(\specifier, +values)
它必须将头部说明符作为第一个参数。其余参数将被转换为 Seq
,然后调用其 head
方法。
例程尾部§
multi method tail() is rawmulti method tail()
返回对象的最后一个元素或 $n
个最后一个元素的列表。$n
可以是 Callable
,通常是 WhateverCode
,它将用于获取对象中除前 n
个元素之外的所有元素。
say (^12).reverse.tail ; # OUTPUT: «0»say (^12).reverse.tail(3); # OUTPUT: «(2 1 0)»say (^12).reverse.tail(*-7); # OUTPUT: «(4 3 2 1 0)»
从 Rakudo 编译器的 2022.07 版本开始,还有一个 tail
的“子”版本。
multi tail(\specifier, +values)
它必须将尾部说明符作为第一个参数。其余参数将被转换为 Seq
,然后调用其 tail
方法。
方法树§
multi method tree(Any:)multi method tree(Any:)multi method tree(Any: Whatever )multi method tree(Any: Int(Cool) )multi method tree(Any: @ [, *])multi method tree(Any: , *)
如果未定义或不是 Iterable
,则返回类,否则返回将其 tree
方法应用于其调用者的结果。
say Any.tree; # OUTPUT: «Any»
.tree
对 Iterable
元素有不同的原型。
my = ( 'A', ('B','C', ('E','F','G')));say .tree(1).flat.elems; # OUTPUT: «6»say .tree(2).flat.elems; # OUTPUT: «2»say .tree( *.join("-"),*.join("—"),*.join("|"));# OUTPUT: «A-B—C—E|F|G»
对于数字,它会迭代地将 tree
应用于较低级别的每个元素;第一个实例将对数组中的每个元素应用 .tree(0)
,下一个示例也是如此。
第二个原型将作为参数传递的 WhateverCode
应用于每个级别;第一个参数将进入级别 1,依此类推。因此,tree
可以成为处理复杂的多级数据结构的所有级别的绝佳方法。
方法 nl-out§
method nl-out(--> Str)
返回值为 "\n" 的 Str
。有关详细信息,请参见 IO::Handle.nl-out
。
Num.nl-out.print; # OUTPUT: «»Whatever.nl-out.print;# OUTPUT: «»33.nl-out.print; # OUTPUT: «»
方法 combinations§
method combinations(|c)
通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.combinations
。
say (^3).combinations; # OUTPUT: «(() (0) (1) (2) (0 1) (0 2) (1 2) (0 1 2))»
对空数据结构的组合将返回一个包含单个元素的列表,即空列表;对包含单个元素的数据结构,它将返回一个包含两个列表的列表,其中一个为空,另一个包含单个元素。
say set().combinations; # OUTPUT: «(())»
方法 grep§
method grep(Mu , :, :, :, : --> Seq)
通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.grep
。
对于未定义的调用者,根据 $matcher
,返回值可以是 ((Any))
或空列表。
my ;say .grep(); # OUTPUT: «((Any))»say .grep(); # OUTPUT: «()»
方法 append§
multi method append(Any \SELF: |values)
如果实例不是位置事物,则将其实例化为一个新的 Array
,否则克隆当前实例。之后,它将作为参数传递的值追加到通过对其调用 Array.append
获得的数组中。
my ;say .append; # OUTPUT: «[]»my ;say .append((1,2,3)); # OUTPUT: «[1 2 3]»
方法值§
multi method values(Any:)multi method values(Any:)
对于未定义或类参数,将返回一个空列表,否则将对象转换为列表。
say (1..3).values; # OUTPUT: «(1 2 3)»say List.values; # OUTPUT: «()»
方法 collate§
method collate()
collate
方法在排序时会考虑 Unicode 图形字符的特性;也就是说,排序方式与人们的预期基本一致,而不是使用代码点出现的顺序。如果 collate
应用于的对象是 Iterable
,它将以这种方式运行。
say ('a', 'Z').sort; # (Z a)say ('a', 'Z').collate; # (a Z)say <ä a o ö>.collate; # (a ä o ö)my = 'aa' => 'value', 'Za' => 'second';say .collate; # (aa => value Za => second);
此方法受 $*COLLATION
变量的影响,该变量配置四个 排序级别。虽然主、次和三级排序对于不同的脚本意味着不同的东西,但对于英语使用的拉丁脚本,它们主要对应于主排序是字母顺序,次排序是变音符号,三级排序是大小写。
在下面的示例中,您可以看到当我们禁用三级排序(在拉丁脚本中通常用于大小写),并禁用四级排序(通过检查字符串的代码点值来打破任何联系)时,我们为 A 和 a 获得了 相同 的结果。
.set(:quaternary(False), :tertiary(False));say 'a' coll 'A'; # OUTPUT: «Same»say ('a','A').collate == ('A','a').collate; # OUTPUT: «True»
该变量会影响 coll
运算符,如所示,以及此方法。
方法 cache§
method cache()
提供对象的 List
表示形式,在实例上调用 list
方法。
方法 batch§
multi method batch(Int )multi method batch(Int :!)
通过应用其 .list
方法将调用者强制转换为 list
,并在其上使用 List.batch
。
方法 rotor§
multi method rotor(Any: Int , :)multi method rotor(Any: *, :)
创建一个 Seq
,将对象中的元素分组到包含 $batch
个元素的列表中。
say (3..9).rotor(3); # OUTPUT: «((3 4 5) (6 7 8))»
使用 :partial
命名参数,它还将包含没有达到 $batch
大小的列表。
say (3..10).rotor(3, :partial); # OUTPUT: «((3 4 5) (6 7 8) (9 10))»
.rotor
可以使用整数和对的数组调用,这些数组将依次应用。虽然整数将建立批次大小(如上所述),但 Pair
将使用键作为批次大小,并将值作为要跳过的元素数量(如果为正),或重叠数量(如果为负)。
say (3..11).rotor(3, 2 => 1, 3 => -2, :partial);# OUTPUT: «((3 4 5) (6 7) (9 10 11) (10 11))»
在这种情况下,第一个批次(由整数控制)包含 3 个元素;第二个批次包含 2 个元素(对的键),但跳过一个(数字 8);第三个批次的大小为 2(因为允许部分),并且重叠也为 2。
重叠不能大于子列表大小;在这种情况下,它将抛出一个 Exception
say (3..11).rotor(3, 2 => 1, 3 => -4, :partial);# OUTPUT: «(exit code 1) Rotorizing gap is out of range. Is: -4, should be in# -3..^Inf; Ensure a negative gap is not larger than the length of the# sublist »
$batch
的非 Int
值将被强制转换为 Int。
say (3..9).rotor(3+⅓); # OUTPUT: «((3 4 5) (6 7 8))»
另请参阅 list.rotor
以获取应用于列表的示例。
方法 sum§
method sum() is nodal
如果内容是可迭代的,它将返回逐个提取值后的总和,如果列表为空,则返回 0。
(3,2,1).sum; # OUTPUT: «6»say 3.sum; # OUTPUT: «3»
如果任何元素无法转换为数字,它将失败。
多方法 slice§
method slice(Any: * --> Seq)
从 Rakudo 编译器 2021.02 版本开始可用。
say (1..10).slice(0, 3..6, 8); # OUTPUT: «(1 4 5 6 7 9)»
例程 snip§
multi snip(\matcher, +values)multi method snip(\values: \matcher)
从 6.e 语言版本开始可用(早期实现存在于 Rakudo 编译器 2022.07+ 中)。
snip
方法/子例程提供了一种将给定的 Iterable
切割成两个或多个 List
的方法。只要给定 Iterable
中的值的智能匹配返回 False,就会进行“剪切”。匹配器也可以是匹配器列表:只要进行了一次“剪切”,它就会开始使用下一个匹配器进行检查。如果不再有匹配器,将生成 Iterable
的其余部分。
.say for snip * < 10, 2, 5, 13, 9, 6; # OUTPUT: «(2 5)(13 9 6)».say for snip (* < 10, * < 20), 5, 13, 29; # OUTPUT: «(5)(13)(29)».say for snip Int, 2, 5, 5, "a", "b"; # OUTPUT: «(2 5 5)(a b)».say for (2, 5, 13, 9, 6).snip(* < 10); # OUTPUT: «(2 5)(13 9 6)».say for (5, 13,29).snip(* < 10, * < 20); # OUTPUT: «(5)(13)(29)».say for (2, 5, 5, "a", "b").snip: Int; # OUTPUT: «(2 5 5)(a b)»
例程 snitch§
multi snitch(\snitchee)multi snitch(, \snitchee)method snitch(\snitchee: = )
从 6.e 语言版本开始可用(早期实现存在于 Rakudo 编译器 2022.12+ 中)。
snitch
方法/子例程是一个调试/日志记录工具,它将始终以不变的形式返回任何调用者/参数。
默认情况下,它会记录调用者/参数,但可以通过指定一个Callable
来覆盖,该Callable
期望将调用者/参数作为其唯一参数。
(my = 42).snitch = 666; say ; # OUTPUT: «42666»(1..5).snitch; # OUTPUT: «1..5»(1..5).Seq.snitch; # OUTPUT: «(1 2 3 4 5)»(1..5).Seq.snitch(); # OUTPUT: «(1, 2, 3, 4, 5).Seq»(1..5).map(*+1).snitch; # OUTPUT: «(2 3 4 5 6)»say (1..3).Seq.snitch.map(*+2); # OUTPUT: «(1 2 3)(3 4 5)»
相同,使用 feed 运算符
(1..3).Seq ==> snitch() ==> map(*+2) ==> say(); # OUTPUT: «(1 2 3)(3 4 5)»
使用自定义日志记录器
my ;my = (1..3).Seq.snitch().map(*+2);say ; # OUTPUT: «[(1 2 3)]»say ; # OUTPUT: «[3 4 5]»