class Range is Cool does Iterable does Positional {}

范围有两个主要用途:生成连续数字或字符串列表,以及充当匹配器以检查数字或字符串是否在某个范围内。

范围使用四个可能的范围运算符之一构建,这些运算符由两个点组成,并且可以包含一个插入符号,该插入符号表示用它标记的端点被排除在范围之外。

1 .. 5;  # 1 <= $x <= 5 
1^.. 5;  # 1 <  $x <= 5 
1 ..^5;  # 1 <= $x <  5 
1^..^5;  # 1 <  $x <  5

插入符号也是用于从零开始构造数字范围的前缀运算符

my $x = 10;
say ^$x;     # same as 0 ..^ $x.Numeric

迭代一个范围(或调用 list 方法)使用与 ++ 前缀和后缀运算符相同的语义,即它调用起点上的 succ 方法,然后调用生成的元素。

范围总是从较小的元素到较大的元素;如果起点大于终点,则范围被认为是空的。

for 1..5 { .say };           # OUTPUT: «1␤2␤3␤4␤5␤» 
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..* { .say };       # start from 1, continue until stopped 
for 1..∞ { .say };       # the same 

请注意,WhateverCode 端点(而不是普通 Whatever)将通过范围运算符并创建另一个 WhateverCode,该 WhateverCode 返回一个 Range

# A Whatever produces the 1..Inf range 
say (1..*).^name;        # OUTPUT: «Range␤» 
say (1..*);              # OUTPUT: «1..Inf␤» 
# Upper end point is now a WhateverCode 
say (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 @numbers =  <4 8 15 16 23 42>;
my $range := 0..2;
.say for @numbers[$range]; # OUTPUT: «4␤8␤15␤» 
my @range = 0..2;
.say for @numbers[@range]; # OUTPUT: «4␤8␤15␤»

移动和缩放区间§

可以移动或缩放范围的区间

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:D: Mu \topic)
multi method ACCEPTS(Range:D: Range \topic)
multi method ACCEPTS(Range:D: Cool:D \got)
multi method ACCEPTS(Range:D: Complex:D \got)

指示 Range 是否包含(与另一个 Range 重叠)。例如

my $p = Range.new35  );
my $r = Range.new110 );
 
say $p.ACCEPTS$r );    # OUTPUT: «False␤» 
say $r.ACCEPTS$p );    # OUTPUT: «True␤» 
say $r ~~ $p;            # OUTPUT: «False␤»  (same as $p.ACCEPTS( $r ) 
say $p ~~ $r;            # 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 方法利用 beforeafter 运算符来检查 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:D:)

返回范围的起始点。

say (1..5).min;                                   # OUTPUT: «1␤» 
say (1^..^5).min;                                 # OUTPUT: «1␤»

方法 excludes-min§

method excludes-min(Range:D: --> Bool:D)

如果起始点被排除在范围之外,则返回 True,否则返回 False

say (1..5).excludes-min;                          # OUTPUT: «False␤» 
say (1^..^5).excludes-min;                        # OUTPUT: «True␤»

方法 max§

method max(Range:D:)

返回范围的结束点。

say (1..5).max;                                   # OUTPUT: «5␤» 
say (1^..^5).max;                                 # OUTPUT: «5␤»

方法 excludes-max§

method excludes-max(Range:D: --> Bool:D)

如果结束点被排除在范围之外,则返回 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:D: --> Bool:D)

如果任一端点用 * 声明,则返回 True

say (1..5).infinite;                              # OUTPUT: «False␤» 
say (1..*).infinite;                              # OUTPUT: «True␤»

方法 is-int§

method is-int(Range:D: --> Bool:D)

如果两个端点都是 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($from is rw$to is rw --> Bool:D)

如果 Range 是整数范围(如 is-int 所示),则此方法返回一个列表,其中包含它将迭代的第一个和最后一个值(考虑 excludes-minexcludes-max)。如果不是整数范围,则返回 Failure

say (2..5).int-bounds;                            # OUTPUT: «(2 5)␤» 
say (2..^5).int-bounds;                           # OUTPUT: «(2 4)␤»

如果使用(可写)参数调用,则这些参数将取较高和较低边界的数值,并返回是否可以从 Range 确定整数边界

if (3..5).int-boundsmy $minmy $max{
    say "$min$max" ; # OUTPUT: «3, 5␤» 
}
else {
    say "Could not determine integer bounds";
}

方法 minmax§

multi method minmax(Range:D: --> List:D)

如果 Range 是整数范围(如 is-int 所示),则此方法返回一个列表,其中包含它将迭代的第一个和最后一个值(考虑 excludes-minexcludes-max)。如果范围不是整数范围,则该方法将返回一个包含范围的起始点和结束点的两个元素列表,除非 excludes-minexcludes-max 中的任何一个为 True,在这种情况下将返回 Failure

my $r1 = (1..5); my $r2 = (1^..5);
say $r1.is-int''$r2.is-int;                 # OUTPUT: «True, True␤» 
say $r1.excludes-min''$r2.excludes-min;     # OUTPUT: «False, True␤» 
say $r1.minmax''$r2.minmax;                 # OUTPUT: «(1 5), (2 5)␤» 
 
my $r3 = (1.1..5.2); my $r4 = (1.1..^5.2);
say $r3.is-int''$r4.is-int;                 # OUTPUT: «False, False␤» 
say $r3.excludes-max''$r4.excludes-max;     # OUTPUT: «False, True␤» 
say $r3.minmax;                                   # OUTPUT: «(1.1 5.2)␤» 
say $r4.minmax;
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::AdHoc: Cannot return minmax on Range with excluded ends␤»

方法 elems§

method elems(Range:D: --> Numeric:D)

返回范围中元素的数量,例如,在进行迭代时,或用作 List 时。如果起始点大于结束点,则返回 0,包括当起始点指定为 时。当范围为惰性时,包括当结束点指定为 或任一结束点指定为 * 时,会失败。

say (1..5).elems;                                 # OUTPUT: «5␤» 
say (1^..^5).elems;                               # OUTPUT: «3␤»

方法列表§

multi method list(Range:D:)

生成范围表示的元素列表。

say (1..5).list;                                  # OUTPUT: «(1 2 3 4 5)␤» 
say (1^..^5).list;                                # OUTPUT: «(2 3 4)␤»

方法 flat§

method flat(Range:D:)

生成一个包含范围表示的元素的 Seq

方法 pick§

multi method pick(Range:D:         --> Any:D)
multi method pick(Range:D: $number --> Seq:D)

执行与 Range.list.pick 相同的功能,但尝试通过在不必要时不实际生成列表来进行优化。

方法 roll§

multi method roll(Range:D:         --> Any:D)
multi method roll(Range:D: $number --> Seq:D)

执行与 Range.list.roll 相同的功能,但尝试通过在不必要时不实际生成列表来进行优化。

方法 sum§

multi method sum(Range:D:)

返回范围内所有元素的总和。如果元素无法强制转换为数字,则抛出 X::Str::Numeric

(1..10).sum                                       # 55

方法 reverse§

method reverse(Range:D: --> Seq:D)

返回一个 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:D: --> Capture:D)

返回一个 Capture,其中 .min .max.excludes-min.excludes-max.infinite.is-int 的值作为命名参数。

方法 rand§

method rand(Range:D --> Num:D)

返回属于该范围的伪随机值。

say (1^..5).rand;                              # OUTPUT: «1.02405550417031␤» 
say (0.1..0.3).rand;                           # OUTPUT: «0.2130353370062␤»

方法 EXISTS-POS§

multi method EXISTS-POS(Range:D: int \pos)
multi method EXISTS-POS(Range:D: 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:D: int \pos)
multi method AT-POS(Range:D: int:D \pos)

检查 Int 位置是否存在,如果存在,则返回该位置中的元素。

say (1..4).AT-POS(2# OUTPUT: «3␤»

方法 raku§

multi method raku(Range:D:)

返回一个特定于实现的字符串,当提供给 EVAL 时,该字符串会生成一个 等效 对象。

say (1..2).raku # OUTPUT: «1..2␤» 

方法 fmt§

method fmt(|c)

返回一个字符串,其中 Range 中的 minmax 已根据 |c 进行格式化。

有关参数的更多信息,请参见 List.fmt

say (1..2).fmt("Element: %d"","# OUTPUT: «Element: 1,Element: 2␤»

方法 WHICH§

multi method WHICH (Range:D:)

这会返回一个标识该对象的字符串。该字符串由实例的类型(Range)以及 minmax 属性组成

say (1..2).WHICH # OUTPUT: «Range|1..2␤»

sub infix:<+>§

multi infix:<+>(Range:D \rReal:D \v)
multi infix:<+>(Real:D \vRange:D \r)

获取一个 Real 并将该数字添加到 Range 对象的两个边界。小心使用括号。

say (1..2+ 2# OUTPUT: «3..4␤» 
say 1..2 + 2;   # OUTPUT: «1..4␤»

sub infix:<->§

multi infix:<->(Range:D \rReal:D \v)

获取一个 Real 并从 Range 对象的两个边界减去该数字。小心使用括号。

say (1..2- 1# OUTPUT: «0..1␤» 
say 1..2 - 1;   # OUTPUT: «1..1␤»

sub infix:<*>§

multi infix:<*>(Range:D \rReal:D \v)
multi infix:<*>(Real:D \vRange:D \r)

获取一个 Real 并将 Range 对象的两个边界乘以该数字。

say (1..2* 2# OUTPUT: «2..4␤»

sub infix:</>§

multi infix:</>(Range:D \rReal:D \v)

获取一个 Real 并将 Range 对象的两个边界除以该数字。

say (2..4/ 2# OUTPUT: «1..2␤»

sub infix:<cmp>§

multi infix:<cmp>(Range:D \aRange:D \b --> Order:D)
multi infix:<cmp>(Num(Real) \aRange:D \b --> Order:D)
multi infix:<cmp>(Range:D \aNum(Real) \b --> Order:D)
multi infix:<cmp>(Positional \aRange:D \b --> Order:D)
multi infix:<cmp>(Range:D \aPositional \b --> Order:D)

比较两个 Range 对象。一个 Real 操作数将被视为一个 Range 的起始点和结束点,以便与另一个操作数进行比较。一个 Positional 操作数将与应用于另一个操作数的 .list 方法 返回的列表进行比较。请参阅 List infix:<cmp>

say (1..2cmp (1..2); # OUTPUT: «Same␤» 
say (1..2cmp (1..3); # OUTPUT: «Less␤» 
say (1..4cmp (1..3); # OUTPUT: «More␤» 
say (1..2cmp 3;      # OUTPUT: «Less␤» 
say (1..2cmp [1,2];  # OUTPUT: «Same␤»

类型图§

Range 的类型关系
raku-type-graph Range Range Cool Cool Range->Cool Positional Positional Range->Positional Iterable Iterable Range->Iterable Mu Mu Any Any Any->Mu Cool->Any

展开上面的图表