is Cool does Iterable does Positional
范围有两个主要用途:生成连续数字或字符串列表,以及充当匹配器以检查数字或字符串是否在某个范围内。
范围使用四个可能的范围运算符之一构建,这些运算符由两个点组成,并且可以包含一个插入符号,该插入符号表示用它标记的端点被排除在范围之外。
1 .. 5; # 1 <= $x <= 51^.. 5; # 1 < $x <= 51 ..^5; # 1 <= $x < 51^..^5; # 1 < $x < 5
插入符号也是用于从零开始构造数字范围的前缀运算符
my = 10;say ^; # same as 0 ..^ $x.Numeric
迭代一个范围(或调用 list
方法)使用与 ++
前缀和后缀运算符相同的语义,即它调用起点上的 succ
方法,然后调用生成的元素。
范围总是从较小的元素到较大的元素;如果起点大于终点,则范围被认为是空的。
for 1..5 ; # OUTPUT: «12345»say ('a' ^..^ 'f').list; # OUTPUT: «(b c d e)»say 5 ~~ ^5; # OUTPUT: «False»say 4.5 ~~ 0..^5; # OUTPUT: «True»say (1.1..5).list; # OUTPUT: «(1.1 2.1 3.1 4.1)»
使用 ...
序列运算符生成从较大值到较小值的元素列表,或使用除增量 1 和其他复杂情况之外的偏移量。
使用 ∞
或 *
(Whatever)表示要开放的端点。
for 1..* ; # start from 1, continue until stoppedfor 1..∞ ; # the same
请注意,WhateverCode
端点(而不是普通 Whatever)将通过范围运算符并创建另一个 WhateverCode,该 WhateverCode 返回一个 Range
# A Whatever produces the 1..Inf rangesay (1..*).^name; # OUTPUT: «Range»say (1..*); # OUTPUT: «1..Inf»# Upper end point is now a WhateverCodesay (1..*+20).^name; # OUTPUT: «{ ... }»say (1..*+20).WHAT; # OUTPUT: «(WhateverCode)»say (1..*+20).(22); # OUTPUT: «1..42»
范围实现 Positional
接口,因此可以使用索引访问其元素。当给定的索引大于 Range 对象的大小时,将返回 Nil
对象。该访问也适用于延迟 Range 对象。
say (1..5)[1]; # OUTPUT: «2»say (1..5)[10]; # OUTPUT: «Nil»say (1..*)[10]; # OUTPUT: «11»
下标中的范围§
范围可用于下标以获取值范围。请注意,将范围分配给标量容器会将范围变成一个项目。使用绑定、@ 符号容器或滑块来获取你的意思。
my = <4 8 15 16 23 42>;my := 0..2;.say for []; # OUTPUT: «4815»my = 0..2;.say for []; # OUTPUT: «4815»
移动和缩放区间§
可以移动或缩放范围的区间
say (1..10) + 1; # OUTPUT: «2..11»say (1..10) - 1; # OUTPUT: «0..9»say (1..10) * 2; # OUTPUT: «2..20»say (1..10) / 2; # OUTPUT: «0.5..5.0»
与范围匹配§
你可以使用 智能匹配 与范围匹配。
say 3 ~~ 1..12; # OUTPUT: «True»say 2..3 ~~ 1..12; # OUTPUT: «True»
仅在 Rakudo 中,你可以使用 in-range
方法与范围匹配,这实际上等效于智能匹配,除了它将在超出范围时引发异常,而不是返回 False
say ('א'..'ת').in-range('ע'); # OUTPUT: «True»
但是,如果它不包含在范围内
say ('א'..'ת').in-range('p', "Letter 'p'");# OUTPUT: «(exit code 1) Letter 'p' out of range. Is: "p", should be in "א".."ת"
in-range
的第二个参数是将与异常一起打印的可选消息。默认情况下,它将打印 Value
。
方法§
方法 ACCEPTS§
multi method ACCEPTS(Range: Mu \topic)multi method ACCEPTS(Range: Range \topic)multi method ACCEPTS(Range: Cool \got)multi method ACCEPTS(Range: Complex \got)
指示 Range
是否包含(与另一个 Range
重叠)。例如
my = Range.new( 3, 5 );my = Range.new( 1, 10 );say .ACCEPTS( ); # OUTPUT: «False»say .ACCEPTS( ); # OUTPUT: «True»say ~~ ; # OUTPUT: «False» (same as $p.ACCEPTS( $r )say ~~ ; # OUTPUT: «True» (same as $r.ACCEPTS( $p )
无限 Range
始终包含任何其他 Range
,因此
say 1..10 ~~ -∞..∞; # OUTPUT: «True»say 1..10 ~~ -∞^..^∞; # OUTPUT: «True»
类似地,具有开放边界的 Range
通常包括其他范围
say 1..2 ~~ *..10; # OUTPUT: «True»say 2..5 ~~ 1..*; # OUTPUT: «True»
还可以使用非数字范围,例如基于字符串的范围
say 'a'..'j' ~~ 'b'..'c'; # OUTPUT: «False»say 'b'..'c' ~~ 'a'..'j'; # OUTPUT: «True»say 'raku' ~~ -∞^..^∞; # OUTPUT: «True»say 'raku' ~~ -∞..∞; # OUTPUT: «True»say 'raku' ~~ 1..*; # OUTPUT: «True»
使用 Cool
(字符串)对整数 Range
进行智能匹配时,ACCEPTS
方法利用 before 和 after 运算符来检查 Cool
值是否与该范围重叠
say 1..10 ~~ '5'; # OUTPUT: «False»say '5' before 1; # OUTPUT: «False»say '5' after 10; # OUTPUT: «True»say '5' ~~ *..10; # OUTPUT: «False»
在上述示例中,由于 '5'
字符串在 10
整数值之后,因此 Range
不与指定值重叠。
与 Mu
实例(即,通用实例)匹配时,将使用 cmp 运算符。
方法 min§
method min(Range:)
返回范围的起始点。
say (1..5).min; # OUTPUT: «1»say (1^..^5).min; # OUTPUT: «1»
方法 excludes-min§
method excludes-min(Range: --> Bool)
如果起始点被排除在范围之外,则返回 True
,否则返回 False
。
say (1..5).excludes-min; # OUTPUT: «False»say (1^..^5).excludes-min; # OUTPUT: «True»
方法 max§
method max(Range:)
返回范围的结束点。
say (1..5).max; # OUTPUT: «5»say (1^..^5).max; # OUTPUT: «5»
方法 excludes-max§
method excludes-max(Range: --> Bool)
如果结束点被排除在范围之外,则返回 True
,否则返回 False
。
say (1..5).excludes-max; # OUTPUT: «False»say (1^..^5).excludes-max; # OUTPUT: «True»
方法 bounds§
method bounds()
返回包含起始点和结束点的列表。
say (1..5).bounds; # OUTPUT: «(1 5)»say (1^..^5).bounds; # OUTPUT: «(1 5)»
方法 infinite§
method infinite(Range: --> Bool)
如果任一端点用 ∞
或 *
声明,则返回 True
。
say (1..5).infinite; # OUTPUT: «False»say (1..*).infinite; # OUTPUT: «True»
方法 is-int§
method is-int(Range: --> Bool)
如果两个端点都是 Int
值,则返回 True
。
say ('a'..'d').is-int; # OUTPUT: «False»say (1..^5).is-int; # OUTPUT: «True»say (1.1..5.5).is-int; # OUTPUT: «False»
方法 int-bounds§
proto method int-bounds(|)multi method int-bounds()multi method int-bounds( is rw, is rw --> Bool)
如果 Range
是整数范围(如 is-int 所示),则此方法返回一个列表,其中包含它将迭代的第一个和最后一个值(考虑 excludes-min 和 excludes-max)。如果不是整数范围,则返回 Failure
。
say (2..5).int-bounds; # OUTPUT: «(2 5)»say (2..^5).int-bounds; # OUTPUT: «(2 4)»
如果使用(可写)参数调用,则这些参数将取较高和较低边界的数值,并返回是否可以从 Range
确定整数边界
if (3..5).int-bounds( my , my )else
方法 minmax§
multi method minmax(Range: --> List)
如果 Range
是整数范围(如 is-int 所示),则此方法返回一个列表,其中包含它将迭代的第一个和最后一个值(考虑 excludes-min 和 excludes-max)。如果范围不是整数范围,则该方法将返回一个包含范围的起始点和结束点的两个元素列表,除非 excludes-min 或 excludes-max 中的任何一个为 True
,在这种情况下将返回 Failure
。
my = (1..5); my = (1^..5);say .is-int, ', ', .is-int; # OUTPUT: «True, True»say .excludes-min, ', ', .excludes-min; # OUTPUT: «False, True»say .minmax, ', ', .minmax; # OUTPUT: «(1 5), (2 5)»my = (1.1..5.2); my = (1.1..^5.2);say .is-int, ', ', .is-int; # OUTPUT: «False, False»say .excludes-max, ', ', .excludes-max; # OUTPUT: «False, True»say .minmax; # OUTPUT: «(1.1 5.2)»say .minmax;CATCH ;# OUTPUT: «X::AdHoc: Cannot return minmax on Range with excluded ends»
方法 elems§
method elems(Range: --> Numeric)
返回范围中元素的数量,例如,在进行迭代时,或用作 List
时。如果起始点大于结束点,则返回 0,包括当起始点指定为 ∞
时。当范围为惰性时,包括当结束点指定为 ∞
或任一结束点指定为 *
时,会失败。
say (1..5).elems; # OUTPUT: «5»say (1^..^5).elems; # OUTPUT: «3»
方法列表§
multi method list(Range:)
生成范围表示的元素列表。
say (1..5).list; # OUTPUT: «(1 2 3 4 5)»say (1^..^5).list; # OUTPUT: «(2 3 4)»
方法 flat§
method flat(Range:)
生成一个包含范围表示的元素的 Seq
。
方法 pick§
multi method pick(Range: --> Any)multi method pick(Range: --> Seq)
执行与 Range.list.pick
相同的功能,但尝试通过在不必要时不实际生成列表来进行优化。
方法 roll§
multi method roll(Range: --> Any)multi method roll(Range: --> Seq)
执行与 Range.list.roll
相同的功能,但尝试通过在不必要时不实际生成列表来进行优化。
方法 sum§
multi method sum(Range:)
返回范围内所有元素的总和。如果元素无法强制转换为数字,则抛出 X::Str::Numeric
。
(1..10).sum # 55
方法 reverse§
method reverse(Range: --> Seq)
返回一个 Seq
,其中 Range
表示的所有元素都已反转。请注意,反转无限 Range
不会产生任何有意义的结果。
say (1^..5).reverse; # OUTPUT: «(5 4 3 2)»say ('a'..'d').reverse; # OUTPUT: «(d c b a)»say (1..∞).reverse; # OUTPUT: «(Inf Inf Inf ...)»
方法 Capture§
method Capture(Range: --> Capture)
返回一个 Capture
,其中 .min
.max
、.excludes-min
、.excludes-max
、.infinite
和 .is-int
的值作为命名参数。
方法 rand§
method rand(Range --> Num)
返回属于该范围的伪随机值。
say (1^..5).rand; # OUTPUT: «1.02405550417031»say (0.1..0.3).rand; # OUTPUT: «0.2130353370062»
方法 EXISTS-POS§
multi method EXISTS-POS(Range: int \pos)multi method EXISTS-POS(Range: Int \pos)
如果 pos
大于或等于零且小于 self.elems
,则返回 True
。否则返回 False
。
say (6..10).EXISTS-POS(2); # OUTPUT: «True»say (6..10).EXISTS-POS(7); # OUTPUT: «False»
方法 AT-POS§
multi method AT-POS(Range: int \pos)multi method AT-POS(Range: int \pos)
检查 Int
位置是否存在,如果存在,则返回该位置中的元素。
say (1..4).AT-POS(2) # OUTPUT: «3»
方法 raku§
multi method raku(Range:)
返回一个特定于实现的字符串,当提供给 EVAL 时,该字符串会生成一个 等效 对象。
say (1..2).raku # OUTPUT: «1..2»
方法 fmt§
method fmt(|c)
返回一个字符串,其中 Range
中的 min
和 max
已根据 |c
进行格式化。
有关参数的更多信息,请参见 List.fmt。
say (1..2).fmt("Element: %d", ",") # OUTPUT: «Element: 1,Element: 2»
方法 WHICH§
multi method WHICH (Range:)
这会返回一个标识该对象的字符串。该字符串由实例的类型(Range
)以及 min
和 max
属性组成
say (1..2).WHICH # OUTPUT: «Range|1..2»
sub infix:<+>§
multi infix:<+>(Range \r, Real \v)multi infix:<+>(Real \v, Range \r)
获取一个 Real
并将该数字添加到 Range
对象的两个边界。小心使用括号。
say (1..2) + 2; # OUTPUT: «3..4»say 1..2 + 2; # OUTPUT: «1..4»
sub infix:<->§
multi infix:<->(Range \r, Real \v)
获取一个 Real
并从 Range
对象的两个边界减去该数字。小心使用括号。
say (1..2) - 1; # OUTPUT: «0..1»say 1..2 - 1; # OUTPUT: «1..1»
sub infix:<*>§
multi infix:<*>(Range \r, Real \v)multi infix:<*>(Real \v, Range \r)
获取一个 Real
并将 Range
对象的两个边界乘以该数字。
say (1..2) * 2; # OUTPUT: «2..4»
sub infix:</>§
multi infix:</>(Range \r, Real \v)
获取一个 Real
并将 Range
对象的两个边界除以该数字。
say (2..4) / 2; # OUTPUT: «1..2»
sub infix:<cmp>§
multi infix:<cmp>(Range \a, Range \b --> Order)multi infix:<cmp>(Num(Real) \a, Range \b --> Order)multi infix:<cmp>(Range \a, Num(Real) \b --> Order)multi infix:<cmp>(Positional \a, Range \b --> Order)multi infix:<cmp>(Range \a, Positional \b --> Order)
比较两个 Range
对象。一个 Real
操作数将被视为一个 Range
的起始点和结束点,以便与另一个操作数进行比较。一个 Positional
操作数将与应用于另一个操作数的 .list
方法 返回的列表进行比较。请参阅 List infix:<cmp>
say (1..2) cmp (1..2); # OUTPUT: «Same»say (1..2) cmp (1..3); # OUTPUT: «Less»say (1..4) cmp (1..3); # OUTPUT: «More»say (1..2) cmp 3; # OUTPUT: «Less»say (1..2) cmp [1,2]; # OUTPUT: «Same»