Rules / Types, classes & roles / composite

Range Reference

Interval of ordered values

What it is #

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method new #

multi method new(Range: \min, \max, :$excludes-min, :$excludes-max)

Creates a new Range with the given minimum and maximum, and with the min and max excluded based on the values passed in the corresponding named arguments.

method 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)

Indicates if the Range contains (overlaps with) another Range. As an example: An infinite Range always contains any other Range, therefore: Similarly, a Range with open boundaries often includes other ranges: It is also possible to use non-numeric ranges, for instance string based ones: say 'a'..'j' ~~ 'b'..'c'; # OUTPUT: «False␤» say 'b'..'c' ~~ 'a'..'j'; # OUTPUT: «True␤» say 'raku' ~~ -∞^..^∞; # OUTPUT: «True␤»

method min #

method min(Range:D:)

Returns the start point of the range.

method excludes-min #

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

Returns Bool:D.

Returns True if the start point is excluded from the range, and False otherwise.

method max #

method max(Range:D:)

Returns the end point of the range.

method excludes-max #

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

Returns Bool:D.

Returns True if the end point is excluded from the range, and False otherwise.

method bounds #

method bounds()

Returns a list consisting of the start and end point.

method infinite #

method infinite(Range:D: --> Bool:D)

Returns Bool:D.

Returns True if either end point was declared with or *.

method is-int #

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

Returns Bool:D.

Returns True if both end points are Int values.

method int-bounds #

proto method int-bounds(|)
multi method int-bounds()
multi method int-bounds($from is rw, $to is rw --> Bool:D)

Returns Bool:D.

If the Range is an integer range (as indicated by is-int), then this method returns a list with the first and last value it will iterate over (taking into account excludes-min and excludes-max). Returns a Failure if it is not an integer range. If called with (writable) arguments, these will take the values of the

method minmax #

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

Returns List:D.

If the Range is an integer range (as indicated by is-int), then this method returns a list with the first and last value it will iterate over (taking into account excludes-min and excludes-max). If the range is not an integer range, the method will return a two element list containing the start and end point of the range unless either of excludes-min or

method elems #

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

Returns Numeric:D.

Returns the number of elements in the range, e.g. when being iterated over, or when used as a List. Returns 0 if the start point is larger than the end point, including when the start point was specified as . Fails when the Range is lazy, including when the end point was specified as or either end point was specified as *.

method list #

multi method list(Range:D:)

Generates the list of elements that the range represents.

method flat #

method flat(Range:D:)

Generates a Seq containing the elements that the range represents.

method pick #

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

Returns Any:D or Seq:D.

Performs the same function as Range.list.pick, but attempts to optimize by not actually generating the list if it is not necessary.

method roll #

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

Returns Any:D or Seq:D.

Performs the same function as Range.list.roll, but attempts to optimize by not actually generating the list if it is not necessary.

method sum #

multi method sum(Range:D:)

Returns the sum of all elements in the Range. Throws X::Str::Numeric if an element can not be coerced into Numeric.

method reverse #

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

Returns Seq:D.

Returns a Seq where all elements that the Range represents have been reversed. Note that reversing an infinite Range won't produce any meaningful results.

method Capture #

method Capture(Range:D: --> Capture:D)

Returns Capture:D.

Returns a Capture with values of .min .max, .excludes-min, .excludes-max, .infinite, and .is-int as named arguments.

method rand #

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

Returns Num:D.

Returns a pseudo-random value belonging to the range.

method EXISTS-POS #

multi method EXISTS-POS(Range:D: int \pos)
multi method EXISTS-POS(Range:D: Int \pos)

Returns True if pos is greater than or equal to zero and lower than self.elems. Returns False otherwise.

method AT-POS #

multi method AT-POS(Range:D: int \pos)
multi method AT-POS(Range:D: int:D \pos)

Checks if the Int position exists and in that case returns the element in that position.

method raku #

multi method raku(Range:D:)

Returns an implementation-specific string that produces an equivalent object when given to EVAL.

method fmt #

method fmt(|c)

Returns a string where min and max in the Range have been formatted according to |c. For more information about parameters, see List.fmt.

method WHICH #

multi method WHICH (Range:D:)

This returns a string that identifies the object. The string is composed by the type of the instance (Range) and the min and max attributes:

sub infix:<+> #

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

Takes a Real and adds that number to both boundaries of the Range object. Be careful with the use of parenthesis.

sub infix:<-> #

multi infix:<->(Range:D \r, Real:D \v)

Takes a Real and subtract that number to both boundaries of the Range object. Be careful with the use of parenthesis.

sub infix:<*> #

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

Takes a Real and multiply both boundaries of the Range object by that number.

sub infix:</> #

multi infix:</>(Range:D \r, Real:D \v)

Takes a Real and divide both boundaries of the Range object by that number.

sub infix:<cmp> #

multi infix:<cmp>(Range:D \a, Range:D \b --> Order:D)
multi infix:<cmp>(Num(Real) \a, Range:D \b --> Order:D)
multi infix:<cmp>(Range:D \a, Num(Real) \b --> Order:D)
multi infix:<cmp>(Positional \a, Range:D \b --> Order:D)
multi infix:<cmp>(Range:D \a, Positional \b --> Order:D)

Returns Order:D.

Compares two Range objects. A Real operand will be considered as both the starting point and the ending point of a Range to be compared with the other operand. A Positional operand will be compared with the list returned by the .list method applied to the other operand. See List infix:<cmp>

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

2 all-differ · 7 no-output · 2 not-runnable · 27 ok · 1 rakudo-differs · 3 rakupp-differs

class Range is Cool does Iterable does Positional {}

Not executed: the documentation states no expected output for this example.

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

Not executed: the documentation states no expected output for this example.

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

Not executed: the documentation states no expected output for this example.

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)␤»
Output
1
2
3
4
5
(b c d e)
False
True
(1.1 2.1 3.1 4.1)

Documentation, Rakudo and Raku++ all agree.

for 1..* { .say };       # start from 1, continue until stopped
for 1..∞ { .say };       # the same

Not executed: the documentation states no expected output for this example.

# 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␤»
Documentation
Range
1..Inf
{ ... }
(WhateverCode)
1..42
Rakudo
Range
1..Inf
WhateverCode.new
(WhateverCode)
1..42
Raku++
Range
1..9223372036854775807
WhateverCode
(WhateverCode)
1..42

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

say (1..5)[1];  # OUTPUT: «2␤»
say (1..5)[10]; # OUTPUT: «Nil␤»
say (1..*)[10]; # OUTPUT: «11␤»
Output
2
Nil
11

Documentation, Rakudo and Raku++ all agree.

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␤»
Output
4
8
15
4
8
15

Documentation, Rakudo and Raku++ all agree.

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␤»
Documentation
2..11
0..9
2..20
0.5..5.0
Rakudo
2..11
0..9
2..20
0.5..5.0
Raku++
2..11
0..9
2..20
0.5..5

Raku++ disagrees with both the documentation and Rakudo — a defect.

say 3 ~~ 1..12;          # OUTPUT: «True␤»
say 2..3 ~~ 1..12;       # OUTPUT: «True␤»
Output
True
True

Documentation, Rakudo and Raku++ all agree.

say ('א'..'ת').in-range('ע');  # OUTPUT: «True␤»
Output
True

Documentation, Rakudo and Raku++ all agree.

say ('א'..'ת').in-range('p', "Letter 'p'");
# OUTPUT: «(exit code 1) Letter 'p' out of range. Is: "p", should be in "א".."ת"␤

Not executed: the documentation states no expected output for this example.

my $p = Range.new( 3, 5  );
my $r = Range.new( 1, 10 );

Not executed: the documentation states no expected output for this example.

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 )

Neither engine can run this in isolation — the example depends on context from the surrounding text.

say 1..10 ~~ -∞..∞;    # OUTPUT: «True␤»
say 1..10 ~~ -∞^..^∞;  # OUTPUT: «True␤»
Output
True
True

Documentation, Rakudo and Raku++ all agree.

say 1..2 ~~ *..10;  # OUTPUT: «True␤»
say 2..5 ~~ 1..*;   # OUTPUT: «True␤»
Output
True
True

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

say ('a'..'d').is-int;                            # OUTPUT: «False␤»
say (1..^5).is-int;                               # OUTPUT: «True␤»
say (1.1..5.5).is-int;                            # OUTPUT: «False␤»
Output
False
True
False

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Raku++ disagrees with both the documentation and Rakudo — a defect.

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)␤»
Output
True, True
False, True
(1 5), (2 5)

Documentation, Rakudo and Raku++ all agree.

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␤»
Documentation
False, False
False, True
(1.1 5.2)
X::AdHoc: Cannot return minmax on Range with excluded ends
Rakudo
False, False
False, True
(1.1 5.2)
X::AdHoc: Cannot return minmax on Range with excluded ends
Raku++
False, False
False, True
(1 5)
(1 4)

Raku++ disagrees with both the documentation and Rakudo — a defect.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

(1..10).sum                                       # 55

Not executed: the documentation states no expected output for this example.

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 ...)␤»

Neither engine can run this in isolation — the example depends on context from the surrounding text.

say (1^..5).rand;                              # OUTPUT: «1.02405550417031␤»
say (0.1..0.3).rand;                           # OUTPUT: «0.2130353370062␤»
Documentation
1.02405550417031
0.2130353370062
Rakudo
2.081674717668394
0.26380444317272733
Raku++
0
0

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

say (6..10).EXISTS-POS(2); # OUTPUT: «True␤»
say (6..10).EXISTS-POS(7); # OUTPUT: «False␤»
Output
True
False

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

say (2..4) / 2; # OUTPUT: «1..2␤»
Documentation
1..2
Rakudo
1.0..2.0
Raku++
1..2

Raku++ matches the documentation; Rakudo does not. This is the one class where neither engine can be assumed right: it may be a stale doc that Raku++ was built from, or it may be a Rakudo bug that the documentation predates. Each case is examined individually.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

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␤»
Output
Same
Less
More
Less
Same

Documentation, Rakudo and Raku++ all agree.