txt: ## range.md
  class Range
  
  Interval of ordered values
  
  ```raku
  class Range is Cool does Iterable does Positional {}
  ```
  
  Ranges serve two main purposes: to generate lists of consecutive numbers or strings, and to act as a matcher to check if a number or string is within a certain range.
  
  Ranges are constructed using one of the four possible range operators, which consist of two dots, and optionally a caret which indicates that the endpoint marked with it is excluded from the range.
  
  ```raku
  1 .. 5;  # 1 <= $x <= 5
  1^.. 5;  # 1 <  $x <= 5
  1 ..^5;  # 1 <= $x <  5
  1^..^5;  # 1 <  $x <  5
  ```
  
  The caret is also a prefix operator for constructing numeric ranges starting from zero:
  
  ```raku
  my $x = 10;
  say ^$x;     # same as 0 ..^ $x.Numeric
  ```
  
  Iterating a range (or calling the `list` method) uses the same semantics as the `++` prefix and postfix operators, i.e., it calls the `succ` method on the start point, and then the generated elements.
  
  Ranges always go from small to larger elements; if the start point is bigger than the end point, the range is considered empty.
  
  ```raku
  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)␤»
  ```
  
  Use the [`...`](/language/operators#infix_...) sequence operator to produce lists of elements that go from larger to smaller values, or to use offsets other than increment-by-1 and other complex cases.
  
  Use `∞` or `*` (Whatever) to indicate an end point to be open-ended.
  
  ```raku
  for 1..* { .say };       # start from 1, continue until stopped
  for 1..∞ { .say };       # the same
  
  ```
  
  Beware that a [`WhateverCode`](/type/WhateverCode) end point, instead of a plain Whatever, will go through the range operator and create another WhateverCode which returns a Range:
  
  ```raku
  # 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␤»
  
  ```
  
  Ranges implement [`Positional`](/type/Positional) interface, so its elements can be accessed using an index. In a case when the index given is bigger than the Range object's size, [`Nil`](/type/Nil) object will be returned. The access works for lazy Range objects as well.
  
  ```raku
  say (1..5)[1];  # OUTPUT: «2␤»
  say (1..5)[10]; # OUTPUT: «Nil␤»
  say (1..*)[10]; # OUTPUT: «11␤»
  
  ```
  
  ## [Ranges in subscripts](#class_Range "go to top of document")[§](#Ranges_in_subscripts "direct link")
  
  A Range can be used in a subscript to get a range of values. Please note that assigning a Range to a scalar container turns the Range into an item. Use binding, @-sigiled containers or a slip to get what you mean.
  
  ```raku
  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␤»
  ```
  
  ## [Shifting and scaling intervals](#class_Range "go to top of document")[§](#Shifting_and_scaling_intervals "direct link")
  
  It is possible to shift or scale the interval of a range:
  
  ```raku
  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␤»
  ```
  
  ## [Matching against Ranges](#class_Range "go to top of document")[§](#Matching_against_Ranges "direct link")
  
  You can use [smartmatch](/routine/~~) to match against Ranges.
  
  ```raku
  say 3 ~~ 1..12;          # OUTPUT: «True␤»
  say 2..3 ~~ 1..12;       # OUTPUT: «True␤»
  ```
  
  *In Rakudo only*, you can use the `in-range` method for matching against a range, which in fact is equivalent to smartmatch except it will throw an exception when out of range, instead of returning `False`:
  
  ```raku
  say ('א'..'ת').in-range('ע');  # OUTPUT: «True␤»
  ```
  
  However, if it is not included in the range:
  
  ```raku
  say ('א'..'ת').in-range('p', "Letter 'p'");
  # OUTPUT: «(exit code 1) Letter 'p' out of range. Is: "p", should be in "א".."ת"␤
  
  ```
  
  The second parameter to `in-range` is the optional message that will be printed with the exception. It will print `Value` by default.
  
  # [Methods](#class_Range "go to top of document")[§](#Methods "direct link")
  
  ## [method ACCEPTS](#class_Range "go to top of document")[§](#method_ACCEPTS "direct link")
  
  ```raku
  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:
  
  ```raku
  my $p = Range.new( 3, 5  );
  my $r = Range.new( 1, 10 );
  
  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 )
  ```
  
  An infinite `Range` always contains any other `Range`, therefore:
  
  ```raku
  say 1..10 ~~ -∞..∞;    # OUTPUT: «True␤»
  say 1..10 ~~ -∞^..^∞;  # OUTPUT: «True␤»
  ```
  
  Similarly, a `Range` with open boundaries often includes other ranges:
  
  ```raku
  say 1..2 ~~ *..10;  # OUTPUT: «True␤»
  say 2..5 ~~ 1..*;   # OUTPUT: «True␤»
  ```
  
  It is also possible to use non-numeric ranges, for instance string based ones:
  
  ```raku
  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␤»
  ```
  
  When smartmatching a `Range` of integers with a [`Cool`](/type/Cool) (string) the `ACCEPTS` methods exploits the [before](/routine/before) and [after](/routine/after) operators in order to check that the [`Cool`](/type/Cool) value is overlapping the range:
  
  ```raku
  say 1..10 ~~ '5';  # OUTPUT: «False␤»
  say '5' before 1;  # OUTPUT: «False␤»
  say '5' after 10;  # OUTPUT: «True␤»
  say '5' ~~ *..10;  # OUTPUT: «False␤»
  ```
  
  In the above example, since the `'5'` string is *after* the `10` integer value, the `Range` does not overlap with the specified value.
  
  When matching with a [`Mu`](/type/Mu) instance (i.e., a generic instance), the [cmp](/routine/cmp) operator is used.
  
  ## [method min](#class_Range "go to top of document")[§](#method_min "direct link")
  
  ```raku
  method min(Range:D:)
  ```
  
  Returns the start point of the range.
  
  ```raku
  say (1..5).min;                                   # OUTPUT: «1␤»
  say (1^..^5).min;                                 # OUTPUT: «1␤»
  ```
  
  ## [method excludes-min](#class_Range "go to top of document")[§](#method_excludes-min "direct link")
  
  ```raku
  method excludes-min(Range:D: --> Bool:D)
  ```
  
  Returns `True` if the start point is excluded from the range, and `False` otherwise.
  
  ```raku
  say (1..5).excludes-min;                          # OUTPUT: «False␤»
  say (1^..^5).excludes-min;                        # OUTPUT: «True␤»
  ```
  
  ## [method max](#class_Range "go to top of document")[§](#method_max "direct link")
  
  ```raku
  method max(Range:D:)
  ```
  
  Returns the end point of the range.
  
  ```raku
  say (1..5).max;                                   # OUTPUT: «5␤»
  say (1^..^5).max;                                 # OUTPUT: «5␤»
  ```
  
  ## [method excludes-max](#class_Range "go to top of document")[§](#method_excludes-max "direct link")
  
  ```raku
  method excludes-max(Range:D: --> Bool:D)
  ```
  
  Returns `True` if the end point is excluded from the range, and `False` otherwise.
  
  ```raku
  say (1..5).excludes-max;                          # OUTPUT: «False␤»
  say (1^..^5).excludes-max;                        # OUTPUT: «True␤»
  ```
  
  ## [method bounds](#class_Range "go to top of document")[§](#method_bounds "direct link")
  
  ```raku
  method bounds()
  ```
  
  Returns a list consisting of the start and end point.
  
  ```raku
  say (1..5).bounds;                                # OUTPUT: «(1 5)␤»
  say (1^..^5).bounds;                              # OUTPUT: «(1 5)␤»
  ```
  
  ## [method infinite](#class_Range "go to top of document")[§](#method_infinite "direct link")
  
  ```raku
  method infinite(Range:D: --> Bool:D)
  ```
  
  Returns `True` if either end point was declared with `∞` or `*`.
  
  ```raku
  say (1..5).infinite;                              # OUTPUT: «False␤»
  say (1..*).infinite;                              # OUTPUT: «True␤»
  ```
  
  ## [method is-int](#class_Range "go to top of document")[§](#method_is-int "direct link")
  
  ```raku
  method is-int(Range:D: --> Bool:D)
  ```
  
  Returns `True` if both end points are [`Int`](/type/Int) values.
  
  ```raku
  say ('a'..'d').is-int;                            # OUTPUT: «False␤»
  say (1..^5).is-int;                               # OUTPUT: «True␤»
  say (1.1..5.5).is-int;                            # OUTPUT: «False␤»
  ```
  
  ## [method int-bounds](#class_Range "go to top of document")[§](#method_int-bounds "direct link")
  
  ```raku
  proto method int-bounds(|)
  multi method int-bounds()
  multi method int-bounds($from is rw, $to is rw --> Bool:D)
  ```
  
  If the `Range` is an integer range (as indicated by [is-int](/routine/is-int)), then this method returns a list with the first and last value it will iterate over (taking into account [excludes-min](/routine/excludes-min) and [excludes-max](/routine/excludes-max)). Returns a [`Failure`](/type/Failure) if it is not an integer range.
  
  ```raku
  say (2..5).int-bounds;                            # OUTPUT: «(2 5)␤»
  say (2..^5).int-bounds;                           # OUTPUT: «(2 4)␤»
  ```
  
  If called with (writable) arguments, these will take the values of the higher and lower bound and returns whether integer bounds could be determined from the `Range`:
  
  ```raku
  if (3..5).int-bounds( my $min, my $max) {
      say "$min, $max" ; # OUTPUT: «3, 5␤»
  }
  else {
      say "Could not determine integer bounds";
  }
  ```
  
  ## [method minmax](#class_Range "go to top of document")[§](#method_minmax "direct link")
  
  ```raku
  multi method minmax(Range:D: --> List:D)
  ```
  
  If the `Range` is an integer range (as indicated by [is-int](/routine/is-int)), then this method returns a list with the first and last value it will iterate over (taking into account [excludes-min](/routine/excludes-min) and [excludes-max](/routine/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](/routine/excludes-min) or [excludes-max](/routine/excludes-max) are `True` in which case a [`Failure`](/type/Failure) is returned.
  
  ```raku
  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␤»
  ```
  
  ## [method elems](#class_Range "go to top of document")[§](#method_elems "direct link")
  
  ```raku
  method elems(Range:D: --> Numeric:D)
  ```
  
  Returns the number of elements in the range, e.g. when being iterated over, or when used as a [`List`](/type/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 `*`.
  
  ```raku
  say (1..5).elems;                                 # OUTPUT: «5␤»
  say (1^..^5).elems;                               # OUTPUT: «3␤»
  ```
  
  ## [method list](#class_Range "go to top of document")[§](#method_list "direct link")
  
  ```raku
  multi method list(Range:D:)
  ```
  
  Generates the list of elements that the range represents.
  
  ```raku
  say (1..5).list;                                  # OUTPUT: «(1 2 3 4 5)␤»
  say (1^..^5).list;                                # OUTPUT: «(2 3 4)␤»
  ```
  
  ## [method flat](#class_Range "go to top of document")[§](#method_flat "direct link")
  
  ```raku
  method flat(Range:D:)
  ```
  
  Generates a [`Seq`](/type/Seq) containing the elements that the range represents.
  
  ## [method pick](#class_Range "go to top of document")[§](#method_pick "direct link")
  
  ```raku
  multi method pick(Range:D:         --> Any:D)
  multi method pick(Range:D: $number --> 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](#class_Range "go to top of document")[§](#method_roll "direct link")
  
  ```raku
  multi method roll(Range:D:         --> Any:D)
  multi method roll(Range:D: $number --> 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](#class_Range "go to top of document")[§](#method_sum "direct link")
  
  ```raku
  multi method sum(Range:D:)
  ```
  
  Returns the sum of all elements in the Range. Throws [`X::Str::Numeric`](/type/X/Str/Numeric) if an element can not be coerced into Numeric.
  
  ```raku
  (1..10).sum                                       # 55
  ```
  
  ## [method reverse](#class_Range "go to top of document")[§](#method_reverse "direct link")
  
  ```raku
  method reverse(Range:D: --> Seq:D)
  ```
  
  Returns a [`Seq`](/type/Seq) where all elements that the `Range` represents have been reversed. Note that reversing an infinite `Range` won't produce any meaningful results.
  
  ```raku
  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 ...)␤»
  
  ```
  
  ## [method Capture](#class_Range "go to top of document")[§](#method_Capture "direct link")
  
  ```raku
  method Capture(Range:D: --> Capture:D)
  ```
  
  Returns a [`Capture`](/type/Capture) with values of [`.min`](/type/Range#method_min) [`.max`](/type/Range#method_max), [`.excludes-min`](/type/Range#method_excludes-min), [`.excludes-max`](/type/Range#method_excludes-max), [`.infinite`](/type/Range#method_infinite), and [`.is-int`](/type/Range#method_is-int) as named arguments.
  
  ## [method rand](#class_Range "go to top of document")[§](#method_rand "direct link")
  
  ```raku
  method rand(Range:D --> Num:D)
  ```
  
  Returns a pseudo-random value belonging to the range.
  
  ```raku
  say (1^..5).rand;                              # OUTPUT: «1.02405550417031␤»
  say (0.1..0.3).rand;                           # OUTPUT: «0.2130353370062␤»
  ```
  
  ## [method EXISTS-POS](#class_Range "go to top of document")[§](#method_EXISTS-POS "direct link")
  
  ```raku
  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.
  
  ```raku
  say (6..10).EXISTS-POS(2); # OUTPUT: «True␤»
  say (6..10).EXISTS-POS(7); # OUTPUT: «False␤»
  ```
  
  ## [method AT-POS](#class_Range "go to top of document")[§](#method_AT-POS "direct link")
  
  ```raku
  multi method AT-POS(Range:D: int \pos)
  multi method AT-POS(Range:D: int:D \pos)
  ```
  
  Checks if the [`Int`](/type/Int) position exists and in that case returns the element in that position.
  
  ```raku
  say (1..4).AT-POS(2) # OUTPUT: «3␤»
  ```
  
  ## [method raku](#class_Range "go to top of document")[§](#method_raku "direct link")
  
  ```raku
  multi method raku(Range:D:)
  ```
  
  Returns an implementation-specific string that produces an [equivalent](/routine/eqv) object when given to [EVAL](/routine/EVAL).
  
  ```raku
  say (1..2).raku # OUTPUT: «1..2␤»
  
  ```
  
  ## [method fmt](#class_Range "go to top of document")[§](#method_fmt "direct link")
  
  ```raku
  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](/type/List#method_fmt).
  
  ```raku
  say (1..2).fmt("Element: %d", ",") # OUTPUT: «Element: 1,Element: 2␤»
  ```
  
  ## [method WHICH](#class_Range "go to top of document")[§](#method_WHICH "direct link")
  
  ```raku
  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:
  
  ```raku
  say (1..2).WHICH # OUTPUT: «Range|1..2␤»
  ```
  
  ## [sub infix:<+>](#class_Range "go to top of document")[§](#sub_infix:<+> "direct link")
  
  ```raku
  multi infix:<+>(Range:D \r, Real:D \v)
  multi infix:<+>(Real:D \v, Range:D \r)
  ```
  
  Takes a [`Real`](/type/Real) and adds that number to both boundaries of the `Range` object. Be careful with the use of parenthesis.
  
  ```raku
  say (1..2) + 2; # OUTPUT: «3..4␤»
  say 1..2 + 2;   # OUTPUT: «1..4␤»
  ```
  
  ## [sub infix:<->](#class_Range "go to top of document")[§](#sub_infix:<-> "direct link")
  
  ```raku
  multi infix:<->(Range:D \r, Real:D \v)
  ```
  
  Takes a [`Real`](/type/Real) and subtract that number to both boundaries of the `Range` object. Be careful with the use of parenthesis.
  
  ```raku
  say (1..2) - 1; # OUTPUT: «0..1␤»
  say 1..2 - 1;   # OUTPUT: «1..1␤»
  ```
  
  ## [sub infix:<\*>](#class_Range "go to top of document")[§](#sub_infix:<*> "direct link")
  
  ```raku
  multi infix:<*>(Range:D \r, Real:D \v)
  multi infix:<*>(Real:D \v, Range:D \r)
  ```
  
  Takes a [`Real`](/type/Real) and multiply both boundaries of the `Range` object by that number.
  
  ```raku
  say (1..2) * 2; # OUTPUT: «2..4␤»
  ```
  
  ## [sub infix:</>](#class_Range "go to top of document")[§](#sub_infix:</> "direct link")
  
  ```raku
  multi infix:</>(Range:D \r, Real:D \v)
  ```
  
  Takes a [`Real`](/type/Real) and divide both boundaries of the `Range` object by that number.
  
  ```raku
  say (2..4) / 2; # OUTPUT: «1..2␤»
  ```
  
  ## [sub infix:<cmp>](#class_Range "go to top of document")[§](#sub_infix:<cmp> "direct link")
  
  ```raku
  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)
  ```
  
  Compares two `Range` objects. A [`Real`](/type/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`](/type/Positional) operand will be compared with the list returned by the [`.list` method](/type/Range#method_list) applied to the other operand. See [`List infix:<cmp>`](/type/List#infix_cmp)
  
  ```raku
  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␤»
  ```
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `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
  
  [Expand chart above](/assets/typegraphs/Range.svg)
  