txt: ## enumeration.md
  role Enumeration
  
  Working with the role behind the enum type
  
  ```raku
  role Enumeration { }
  ```
  
  This is the role implemented by the enum-pairs in the [`enum` type](/language/typesystem#enum). In general, it is used to create constant sets, the elements of which become also constant symbols in the current namespace and to establish a relationship between the symbols belonging to the same set. In general, you will find `Enumeration` in [enum](/language/typesystem#enum) types:
  
  ```raku
  enum norse-gods <Þor Oðin Loki>;
  my $one-of-them = norse-gods.pick;
  say $one-of-them ~~ Enumeration; # OUTPUT: «True␤»
  ```
  
  but nothing prevents you from using it in your own programs if you want to restrict somehow the relationship between the key and the value:
  
  ```raku
  class DNA does Enumeration {
      my %pairings = %( A => "T",
                        T => "A",
                        C => "G",
                        G => "C" );
  
      method new( $base-pair where "A" | "C" | "G" | "T" )  {
          self.bless( key => $base-pair,
                      value => %pairings{$base-pair});
      }
  
      multi method gist(::?CLASS:D:) {
          return "$!key → $!value";
      }
  
  }
  
  enum Chain ();
  constant length = 16;
  for <A C G T>.roll( length ) -> $letter {
      my DNA $base = DNA.new( $letter );
      Chain.HOW.add_enum_value( Chain, $base );
  }
  
  for ^length {
      my $base = Chain.pick;
      say "{$base.key} and {$base.value}";
  }
  
  ```
  
  In this code, `DNA` consumes the `Enumeration` role, which is from this point of view a pair of key and value; we can use the generated `DNA` objects to compose an `enum` type from which elements can be picked one by one, with the output shown below.
  
  ｢text｣ without highlighting
  
  ```
  
  
  ```
  
  T and A
  C and G
  T and A
  # and so on...
  
  
  ```
  
  
  ```
  
  An item would smartmatch the enum class, but not the other way round:
  
  ```raku
  enum Foo <bar baz>;
  say baz ~~ Foo;  # OUTPUT: «True␤»
  say Foo ~~ bar;  # OUTPUT: «False␤»
  
  ```
  
  # [Methods that work on the enum class](#role_Enumeration "go to top of document")[§](#Methods_that_work_on_the_enum_class "direct link")
  
  As of release 2021.04 of the Rakudo compiler, an enum class can be considered as an instantiated [`Map`](/type/Map) object. This means you can use the [keys](/type/Map#method_keys), [values](/type/Map#method_values), [kv](/type/Map#method_kv), [pairs](/type/Map#method_pairs), [antipairs](/type/Map#method_antipairs), [invert](/type/Map#method_invert) on an enum class and get the expected result.
  
  ```raku
  enum Norse-gods <Þor Oðin Freija>;
  say Norse-gods.keys; # OUTPUT: «(Þor Oðin Freija)␤»
  ```
  
  ## [method enums](#role_Enumeration "go to top of document")[§](#method_enums "direct link")
  
  ```raku
  method enums()
  ```
  
  Returns a [`Map`](/type/Map) of enum values. Works both on the enum type and any key.
  
  ```raku
  enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 );
  say Mass.enums; # OUTPUT: «Map.new((g => 1, kg => 1000, mg => 0.001))␤»
  say g.enums;    # OUTPUT: «Map.new((g => 1, kg => 1000, mg => 0.001))␤»
  ```
  
  # [Methods that work on the enum keys](#role_Enumeration "go to top of document")[§](#Methods_that_work_on_the_enum_keys "direct link")
  
  ## [method key](#role_Enumeration "go to top of document")[§](#method_key "direct link")
  
  An `Enumeration` property.
  
  ```raku
  enum Norse-gods <Þor Oðin Freija>;
  say Freija.key; # OUTPUT: «Freija␤»
  ```
  
  ## [method value](#role_Enumeration "go to top of document")[§](#method_value "direct link")
  
  These are `Enumeration` properties.
  
  ```raku
  enum Norse-gods <Þor Oðin Freija>;
  say Oðin.value; # OUTPUT: «1␤»
  ```
  
  The `value` is assigned automatically by the `enum` type starting at 0. `Oðin` gets 1 since it is the second in the `enum`.
  
  ## [method kv](#role_Enumeration "go to top of document")[§](#method_kv "direct link")
  
  ```raku
  multi method kv(::?CLASS:D:)
  ```
  
  Returns a list with key and value of the enum-pair.
  
  ```raku
  say g.kv; # OUTPUT: «(g 1)␤»
  
  ```
  
  ## [method pair](#role_Enumeration "go to top of document")[§](#method_pair "direct link")
  
  ```raku
  method pair(::?CLASS:D:)
  ```
  
  Returns it as a [`Pair`](/type/Pair).
  
  ```raku
  say g.pair; # OUTPUT: «g => 1␤»
  
  ```
  
  ## [method CALL-ME](#role_Enumeration "go to top of document")[§](#method_CALL-ME "direct link")
  
  ```raku
  multi method CALL-ME(|)
  ```
  
  Returns an `Enumeration` instance given an enum value.
  
  ```raku
  enum Mass ( mg => 1/1000, g => 1/1, kg => 1000/1 );
  say Mass(1/1000); # OUTPUT: mg
  ```
  
  ## [method pick](#role_Enumeration "go to top of document")[§](#method_pick "direct link")
  
  ```raku
  multi method pick(::?CLASS:U:)
  multi method pick(::?CLASS:U: \n)
  multi method pick(::?CLASS:D: *@pos)
  ```
  
  It works on the defined class, selecting one element and eliminating it.
  
  ```raku
  say Norse-gods.pick() for ^3;  # OUTPUT: «Þor␤Freija␤Oðin␤»
  
  ```
  
  ## [method roll](#role_Enumeration "go to top of document")[§](#method_roll "direct link")
  
  ```raku
  multi method roll(::?CLASS:U:)
  multi method roll(::?CLASS:U: \n)
  multi method roll(::?CLASS:D: *@pos)
  ```
  
  They work on the defined class selecting one or `n` elements without eliminating them.
  
  ```raku
  say Norse-gods.roll() for ^3;  # OUTPUT: «Freija␤Freija␤Oðin␤»
  
  ```
  
  ## [method pred](#role_Enumeration "go to top of document")[§](#method_pred "direct link")
  
  ```raku
  method pred(::?CLASS:D:)
  ```
  
  ```raku
  say Freija.pred;  # OUTPUT: «Oðin␤»
  
  ```
  
  ## [method succ](#role_Enumeration "go to top of document")[§](#method_succ "direct link")
  
  ```raku
  method succ(::?CLASS:D:)
  ```
  
  ```raku
  say Oðin.succ;  # OUTPUT: «Freija␤»
  
  ```
  
  ## [method Numeric](#role_Enumeration "go to top of document")[§](#method_Numeric "direct link")
  
  ```raku
  multi method Numeric(::?CLASS:D:)
  ```
  
  Takes a value of an enum and returns it after coercion to [`Numeric`](/type/Numeric):
  
  ```raku
  enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' );
  say cool.Numeric;       # OUTPUT: «42␤»
  say almost-pi.Numeric;  # OUTPUT: «3.14␤»
  say sqrt-n-one.Numeric; # OUTPUT: «0+1i␤»
  ```
  
  Note that if the value cannot be coerced to [`Numeric`](/type/Numeric), an exception will be thrown.
  
  ## [method Int](#role_Enumeration "go to top of document")[§](#method_Int "direct link")
  
  ```raku
  multi method Int(::?CLASS:D:)
  ```
  
  Takes a value of an enum and returns it after coercion to [`Int`](/type/Int):
  
  ```raku
  enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' );
  say cool.Int;           # OUTPUT: «42␤»
  say almost-pi.Int;      # OUTPUT: «3␤»
  try say sqrt-n-one.Int;
  say $!.message if $!;   # OUTPUT: «Cannot convert 0+1i to Int: imaginary part not zero␤»
  ```
  
  Note that if the value cannot be coerced to [`Int`](/type/Int), an exception will be thrown.
  
  ## [method Real](#role_Enumeration "go to top of document")[§](#method_Real "direct link")
  
  ```raku
  multi method Real(::?CLASS:D:)
  ```
  
  Takes a value of an enum and returns it after coercion to [`Real`](/type/Real):
  
  ```raku
  enum Numbers ( cool => '42', almost-pi => '3.14', sqrt-n-one => 'i' );
  say cool.Real;           # OUTPUT: «42␤»
  say almost-pi.Real;      # OUTPUT: «3.14␤»
  try say sqrt-n-one.Real;
  say $!.message if $!;    # OUTPUT: «Cannot convert 0+1i to Real: imaginary part not zero␤»
  ```
  
  Note that if the value cannot be coerced to [`Real`](/type/Real), an exception will be thrown.
  
  ## [method `===`](#role_Enumeration "go to top of document")[§](#method_=== "direct link")
  
  ```raku
  multi infix:<===> (Enumeration:D \a, Enumeration:D \b)
  ```
  
  Equality of `Enumeration` symbols:
  
  ```raku
  say Norse-gods.pick() === Freija for ^3; # OUTPUT: «False␤False␤True␤»
  
  ```
  
  # [Typegraph](# "go to top of document")[§](#typegraphrelations "direct link")
  
  Type relations for `Enumeration`
  
  
  
  raku-type-graph
  
  
  
  Enumeration
  Enumeration
  
  [Expand chart above](/assets/typegraphs/Enumeration.svg)
  