txt: ## subscripts.md
  ## Chunk 2 of 2
   = Jan => 1, Feb => 2, Mar => 3;
  say %month<Feb>:k;          # OUTPUT: «Feb␤»
  say %month<Jan Foo Mar>:k;  # OUTPUT: «(Jan Mar)␤»
  ```
  
  If you *don't* want to skip nonexistent elements, use the negated form:
  
  ```raku
  say %month<Jan Foo Mar>:!k;  # OUTPUT: «(Jan Foo Mar)␤»
  
  ```
  
  See also the [keys](/routine/keys) routine.
  
  ## [`:v`](#Subscripts "go to top of document")[§](#:v "direct link")
  
  Return the bare value of the element (rather than potentially returning a mutable value container), and silently skip nonexistent elements:
  
  ```raku
  my @tens = 0, 10, 20, 30;
  say @tens[1]:v;        # OUTPUT: «10␤»
  say @tens[0, 4, 2]:v;  # OUTPUT: «(0, 20)␤»
  @tens[3] = 31;         # OK
  @tens[3]:v = 31;       # ERROR, Cannot modify an immutable Int (31)
  
  my %month = Jan => 1, Feb => 2, Mar => 3;
  say %month<Feb>:v;          # OUTPUT: «2␤»
  say %month<Jan Foo Mar>:v;  # OUTPUT: «(1 3)␤»
  
  ```
  
  If you *don't* want to skip nonexistent elements, use the negated form:
  
  ```raku
  say %month<Jan Foo Mar>:!v;  # OUTPUT: «(1 (Any) 3)␤»
  
  ```
  
  See also the [values](/routine/values) routine.
  
  # [Custom types](#Subscripts "go to top of document")[§](#Custom_types "direct link")
  
  The subscripting interfaces described on this page are not meant to be exclusive to Raku's built-in collection types - you can (and should) reuse them for any custom type that wants to provide access to data by index or key.
  
  You don't have to manually overload the [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) and [`postcircumfix { }`](/language/operators#postcircumfix_{_}) operators and re-implement all their magic, to achieve that - instead, you can rely on the fact that their standard implementation dispatches to a well-defined set of low-level methods behind the scenes. For example:
  
  | when you write: | this gets called behind the scenes: |
  | --- | --- |
  | %foo<aa> | %foo.AT-KEY("aa") |
  | %foo<aa>:delete | %foo.DELETE-KEY("aa") |
  | @foo[3, 4, 5] | @foo.AT-POS(3), @foo.AT-POS(4), @foo.AT-POS(5) |
  | @foo[\*-1] | @foo.AT-POS(@foo.elems - 1) |
  
  So in order to make subscripting work, you only have to implement or delegate those low-level methods ([detailed below](#Methods_to_implement_for_positional_subscripting)) for your custom type.
  
  If you do, you should also let your type compose the [`Positional`](/type/Positional) or [`Associative`](/type/Associative) role, respectively. This doesn't add any functionality per se, but announces (and may be used to check) that the type implements the corresponding subscripting interface.
  
  ## [Custom type example](#Subscripts "go to top of document")[§](#Custom_type_example "direct link")
  
  Imagine a `HTTP::Header` type which, despite being a custom class with special behavior, can be indexed like a hash:
  
  ```raku
  my $request = HTTP::Request.new(GET => "raku.org");
  say $request.header.^name;  # OUTPUT: «HTTP::Header␤»
  
  $request.header<Accept> = "text/plain";
  $request.header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>;
  $request.header.push('Accept-Language' => "fr");  # like .push on a Hash
  
  say $request.header<Accept-Language>.raku;  # OUTPUT: «["en", "fr"]␤»
  
  my $rawheader = $request.header.Str;  # stringify according to HTTP spec
  
  ```
  
  A simple way to implement this class would be to give it an attribute of type [`Hash`](/type/Hash), and delegate all subscripting and iterating related functionality to that attribute (using a custom type constraint to make sure users don't insert anything invalid into it):
  
  ```raku
  class HTTP::Header does Associative {
      subset StrOrArrayOfStr where Str | ( Array & {.all ~~ Str} );
  
      has %!fields of StrOrArrayOfStr
                   handles <AT-KEY EXISTS-KEY DELETE-KEY push
                            iterator list kv keys values>;
  
      method Str { #`[not shown, for brevity] }
  }
  
  ```
  
  However, HTTP header field names are supposed to be case-insensitive (and preferred in camel-case). We can accommodate this by taking the `*-KEY` and `push` methods out of the `handles` list, and implementing them separately like this:
  
  ```raku
  method AT-KEY     ($key) is rw { %!fields{normalize-key $key}        }
  method EXISTS-KEY ($key)       { %!fields{normalize-key $key}:exists }
  method DELETE-KEY ($key)       { %!fields{normalize-key $key}:delete }
  method push(*@_) { #`[not shown, for brevity] }
  
  sub normalize-key ($key) { $key.subst(/\w+/, *.tc, :g) }
  
  ```
  
  Note that subscripting `%!fields` returns an appropriate rw container, which our `AT-KEY` can simply pass on.
  
  However, we may prefer to be less strict about user input and instead take care of sanitizing the field values ourselves. In that case, we can remove the `StrOrArrayOfStr` type constraint on `%!fields`, and replace our `AT-KEY` implementation with one that returns a custom [`Proxy`](/type/Proxy) container which takes care of sanitizing values on assignment:
  
  ```raku
  multi method AT-KEY (::?CLASS:D: $key) is rw {
      my $element := %!fields{normalize-key $key};
  
      Proxy.new(
          FETCH => method () { $element },
  
          STORE => method ($value) {
              $element = do given $value».split(/',' \s+/).flat {
                  when 1  { .[0] }    # a single value is stored as a string
                  default { .Array }  # multiple values are stored as an array
              }
          }
      );
  }
  
  ```
  
  Note that declaring the method as `multi` and restricting it to `:D` (defined invocants) makes sure that the undefined case is passed through to the default implementation provided by [`Any`](/type/Any) (which is involved in auto-vivification).
  
  ## [Methods to implement for positional subscripting](#Subscripts "go to top of document")[§](#Methods_to_implement_for_positional_subscripting "direct link")
  
  In order to make index-based subscripting via [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) work for your custom type, you should implement at least `elems`, `AT-POS` and `EXISTS-POS` - and optionally others as detailed below.
  
  ### [method elems](#Subscripts "go to top of document")[§](#method_elems "direct link")
  
  ```raku
  multi method elems(::?CLASS:D:)
  ```
  
  Expected to return a number indicating how many subscriptable elements there are in the object. May be called by users directly, and is also called by [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) when indexing elements from the end, as in `@foo[*-1]`.
  
  If not implemented, your type will inherit the default implementation from [`Any`](/type/Any) that always returns `1` for defined invocants - which is most likely not what you want. So if the number of elements cannot be known for your positional type, add an implementation that [fail](/routine/fail)s or [die](/routine/die)s, to avoid silently doing the wrong thing.
  
  ### [method AT-POS](#Subscripts "go to top of document")[§](#method_AT-POS "direct link")
  
  ```raku
  multi method AT-POS (::?CLASS:D: $index)
  ```
  
  Expected to return the element at position `$index`. This is what [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) normally calls.
  
  If you want an element to be mutable (like they are for the built-in [`Array`](/type/Array) type), you'll have to make sure to return it in the form of an item container that evaluates to the element's value when read, and updates it when assigned to. Remember to use `return-rw` or the `is rw` routine trait to make that work; see the [example](/language/subscripts#Custom_type_example).
  
  ### [method EXISTS-POS](#Subscripts "go to top of document")[§](#method_EXISTS-POS "direct link")
  
  ```raku
  multi method EXISTS-POS (::?CLASS:D: $index)
  ```
  
  Expected to return a Bool indicating whether or not there is an element at position `$index`. This is what [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) calls when invoked like `@foo[42]:exists`.
  
  What "existence" of an element means, is up to your type.
  
  If you don't implement this, your type will inherit the default implementation from [`Any`](/type/Any), which returns True for 0 and False for any other index - which is probably not what you want. So if checking for element existence cannot be done for your type, add an implementation that [fail](/routine/fail)s or [die](/routine/die)s, to avoid silently doing the wrong thing.
  
  ### [method DELETE-POS](#Subscripts "go to top of document")[§](#method_DELETE-POS "direct link")
  
  ```raku
  multi method DELETE-POS (::?CLASS:D: $index)
  ```
  
  Expected to delete the element at position `$index`, and return the value it had. This is what [`postcircumfix [ ]`](/language/operators#postcircumfix_[_]) calls when invoked like `@foo[42]:delete`.
  
  What "deleting" an element means, is up to your type.
  
  Implementing this method is optional; if you don't, users trying to delete elements from an object of this type will get an appropriate error message.
  
  ### [method ASSIGN-POS](#Subscripts "go to top of document")[§](#method_ASSIGN-POS "direct link")
  
  ```raku
  multi method ASSIGN-POS (::?CLASS:D: $index, $new)
  ```
  
  Expected to set the element at position `$index` to the value `$new`. Implementing this is entirely optional; if you don't, `self.AT-POS($index) = $new` is used instead, and if you do, you should make sure it has the same effect.
  
  This is meant as an opt-in performance optimization, so that simple assignments like `@numbers[5] = "five"` can operate without having to call `AT-POS` (which would have to create and return a potentially expensive container object).
  
  Note that implementing `ASSIGN-POS` does *not* relieve you from making `AT-POS` a `rw` method though, because less trivial assignments/modifications such as `@numbers[5]++` will still use `AT-POS`.
  
  ### [method BIND-POS](#Subscripts "go to top of document")[§](#method_BIND-POS "direct link")
  
  ```raku
  multi method BIND-POS (::?CLASS:D: $index, \new)
  ```
  
  Expected to bind the value or container `new` to the slot at position `$index`, replacing any container that would be naturally found there. This is what is called when you write:
  
  ```raku
  my $x = 10;
  @numbers[5] := $x;
  
  ```
  
  The generic [`Array`](/type/Array) class supports this in order to allow building complex linked data structures, but for more domain-specific types it may not make sense, so don't feel compelled to implement it. If you don't, users will get an appropriate error message when they try to bind to a positional slot of an object of this type.
  
  ### [method STORE](#Subscripts "go to top of document")[§](#method_STORE "direct link")
  
  ```raku
  method STORE (::?CLASS:D: \values, :$INITIALIZE)
  ```
  
  This method should only be supplied if you want to support this syntax:
  
  ```raku
  my @a is Foo = 1,2,3;
  
  ```
  
  Which is used for binding your implementation of the [`Positional`](/type/Positional) role.
  
  `STORE` should accept the values to (re-)initialize the object with. The optional named parameter will contain a `True` value when the method is called on the object for the first time. It should return the invocant.
  
  ```raku
  role Logger { method log( Str $msg) {…}}
  
  class ConsoLogger does Logger { method log ( Str $msg ) { "❢ $msg".say }}
  
  class DNA {
      has $.chain;
      has Logger $!logger;
  
      submethod BUILD( :$chain, :$logger = ConsoLogger.new() ) {}
  
      method STORE (Str $chain where {
              /^^ <[ACGT]>+ $$ / and
              .chars %% 3
          },
          :$INITIALIZE --> DNA) {
  
          if ($INITIALIZE) {
              $!logger = ConsoLogger.new();
              $!logger.log( "Initialized" );
          }
  
          $!chain  := $chain;
          $!logger.log("Change value to $chain" );
          self
      }
  
      method Str(::?CLASS:D:) { return $!chain.comb.rotor(3).map( *.join("")).join("|") }
  };
  
  my @string is DNA = 'GAATCC';    # OUTPUT: «❢ Initialized␤❢ Change value to GAATCC␤»
  say ~@string;                    # OUTPUT: «GAA|TCC␤»
  @string = 'ACGTCG';              # OUTPUT: «❢ Change value to ACGTCG␤»
  say  ~@string;                   # OUTPUT: «ACG|TCG␤»
  
  ```
  
  This code takes into account the value of `$INITIALIZE`, which is set to `True` only if we are assigning a value to a variable declared using the `is` syntax for the first time; for instance, as in this case, we might need to initialize any injected dependency. The `STORE` method should set the `self` variable and return it in all cases, including when the variable has already been initialized; however, only in the first case we need to initialize the logger we are using in this example.
  
  The presence of the `INITIALIZE` flag can be also used to create immutable data structures:
  
  ```raku
  class A {
      has @.foo handles <Str gist raku>;
      multi method STORE(*@!foo, :$INITIALIZE!) { }
      multi method STORE(|) { die "Immutable" }
  }
  
  my @a is A = 1,2,3,4;
  say @a;        # OUTPUT: «[1,2,3,4]␤»
  @a = 4,5,6,7;  # dies: Immutable
  
  ```
  
  ## [Methods to implement for associative subscripting](#Subscripts "go to top of document")[§](#Methods_to_implement_for_associative_subscripting "direct link")
  
  In order to make key-based subscripting via [`postcircumfix { }`](/language/operators#postcircumfix_{_}) work for your custom type, you should implement at least `AT-KEY` and `EXISTS-KEY` - and optionally others as detailed below.
  
  ### [method AT-KEY](#Subscripts "go to top of document")[§](#method_AT-KEY "direct link")
  
  ```raku
  multi method AT-KEY (::?CLASS:D: $key)
  ```
  
  Expected to return the element associated with `$key`. This is what [`postcircumfix { }`](/language/operators#postcircumfix_{_}) normally calls.
  
  If you want an element to be mutable (like they are for the built-in [`Hash`](/type/Hash) type), you'll have to make sure to return it in the form of an item container that evaluates to the element's value when read, and updates it when assigned to. Remember to use `return-rw` or the `is rw` routine trait to make that work; see the [example](/language/subscripts#Custom_type_example).
  
  On the other hand if you want your collection to be read-only, feel free to return non-container values directly.
  
  ### [method EXISTS-KEY](#Subscripts "go to top of document")[§](#method_EXISTS-KEY "direct link")
  
  ```raku
  multi method EXISTS-KEY (::?CLASS:D: $key)
  ```
  
  Expected to return a Bool indicating whether or not there is an element associated with `$key`. This is what [`postcircumfix { }`](/language/operators#postcircumfix_{_}) calls when invoked like `%foo<aa>:exists`.
  
  What "existence" of an element means, is up to your type.
  
  If you don't implement this, your type will inherit the default implementation from [`Any`](/type/Any), which always returns False - which is probably not what you want. So if checking for element existence cannot be done for your type, add an implementation that [fail](/routine/fail)s or [die](/routine/die)s, to avoid silently doing the wrong thing.
  
  ### [method DELETE-KEY](#Subscripts "go to top of document")[§](#method_DELETE-KEY "direct link")
  
  ```raku
  multi method DELETE-KEY (::?CLASS:D: $key)
  ```
  
  Expected to delete the element associated with `$key`, and return the value it had. This is what [`postcircumfix { }`](/language/operators#postcircumfix_{_}) calls when invoked like `%foo<aa>:delete`.
  
  What "deleting" an element means, is up to your type - though it should usually cause `EXISTS-KEY` to become `False` for that key.
  
  Implementing this method is optional; if you don't, users trying to delete elements from an object of this type will get an appropriate error message.
  
  ### [method ASSIGN-KEY](#Subscripts "go to top of document")[§](#method_ASSIGN-KEY "direct link")
  
  ```raku
  multi method ASSIGN-KEY (::?CLASS:D: $key, $new)
  ```
  
  Expected to set the element associated with `$key` to the value `$new`. Implementing this is entirely optional; if you don't, `self.AT-KEY($key) = $new` is used instead, and if you do, you should make sure it has the same effect.
  
  This is meant as an opt-in performance optimization, so that simple assignments `%age<Claire> = 29` can operate without having to call `AT-KEY` (which would have to create and return a potentially expensive container object).
  
  Note that implementing `ASSIGN-KEY` does *not* relieve you from making `AT-KEY` a `rw` method though, because less trivial assignments/modifications such as `%age<Claire>++` will still use `AT-KEY`.
  
  ### [method BIND-KEY](#Subscripts "go to top of document")[§](#method_BIND-KEY "direct link")
  
  ```raku
  multi method BIND-KEY (::?CLASS:D: $key, \new)
  ```
  
  Expected to bind the value or container `new` to the slot associated with `$key`, replacing any container that would be naturally found there. This is what is called when you write:
  
  ```raku
  my $x = 10;
  %age<Claire> := $x;
  
  ```
  
  The generic [`Hash`](/type/Hash) class supports this in order to allow building complex linked data structures, but for more domain-specific types it may not make sense, so don't feel compelled to implement it. If you don't, users will get an appropriate error message when they try to bind to an associative slot of an object of this type.
  
  ### [method STORE](#Subscripts "go to top of document")[§](#method_STORE_0 "direct link")
  
  ```raku
  method STORE (::?CLASS:D: \values, :$INITIALIZE)
  ```
  
  This method should only be supplied if you want to support the:
  
  ```raku
  my %h is Foo = a => 42, b => 666;
  
  ```
  
  syntax for binding your implementation of the [`Associative`](/type/Associative) role.
  
  Should accept the values to (re-)initialize the object with, which either could consist of [`Pair`](/type/Pair)s, or separate key/value pairs. The optional named parameter will contain a `True` value when the method is called on the object for the first time. Should return the invocant.
  