txt: ## typesystem.md
  ## Chunk 1 of 2
  Type system
  
  Introduction to the type system of Raku
  
  # [Definition of a Raku type](#Type_system "go to top of document")[§](#Definition_of_a_Raku_type "direct link")
  
  A type defines a new object by creating a type object that provides an interface to create instances of objects or to check values against. Any type object is a subclass of [`Any`](/type/Any) or [`Mu`](/type/Mu). Introspection methods are provided via inheritance from those base classes and the introspection metamethods ([.^](/language/operators#methodop_.^)). A new type is introduced to the current scope by one of the following type declarators at compile time or with the [metaobject protocol](/language/mop) at runtime. All type names must be unique in their scope.
  
  ## [Default types](#Type_system "go to top of document")[§](#Default_types "direct link")
  
  If no type is provided by the user Raku assumes the type to be [`Any`](/type/Any). This includes [containers](/language/containers), base-classes, [parameters](/language/signatures#Type_constraints) and return types.
  
  ```raku
  my $a = 1;
  $a = Nil;
  say $a.^name;
  # OUTPUT: «Any␤»
  
  class C {};
  say C.^parents(:all);
  # OUTPUT: «((Any) (Mu))␤»
  ```
  
  For containers the default type is [`Any`](/type/Any) but the default type constraint is [`Mu`](/type/Mu). Please note that binding replaces the container, not just the value. The type constraint may change in this case.
  
  ## [Type objects](#Type_system "go to top of document")[§](#Type_objects "direct link")
  
  To test if an object is a type object, use [smartmatch](/language/operators#index-entry-smartmatch_operator) against a type constrained with a [type smiley](/language/signatures#Constraining_argument_definiteness) or [`.DEFINITE`](/language/mop#DEFINITE) method:
  
  ```raku
  my $a = Int;
  say $a ~~ Mu:U;
  # OUTPUT: «True␤»
  say not $a.DEFINITE;
  # OUTPUT: «True␤»
  
  ```
  
  `.DEFINITE` will return `True` if the invocant is an instance. If it returns `False`, then the invocant is a type object.
  
  ### [Undefinedness](#Type_system "go to top of document")[§](#Undefinedness "direct link")
  
  Undefined objects maintain type information in Raku. Type objects are used to represent both undefinedness and the type of the undefined value. To provide a general undefined value use [`Any`](/type/Any). If differentiation from [`Any`](/type/Any), the default type for containers and arguments, is required use [`Mu`](/type/Mu).
  
  Instances of objects created by [.CREATE](/type/Mu#method_CREATE) are by convention defined. The method [.defined](/type/Mu#routine_defined) will return `Bool::True` to indicate definedness. The exceptions to that rule are [`Nil`](/type/Nil) and [`Failure`](/type/Failure). Please note that any object is able to overload `.defined` and as such can carry additional information. Also, Raku makes a clear distinction between definedness and trueness. Many values are defined even though they carry the meaning of wrongness or emptiness. Such values are `0`, [Bool::False](/type/Bool), [()](/language/operators#term_(_)) (empty list) and [`NaN`](/type/Num#NaN).
  
  Values can become undefined at runtime via [mixin](/language/operators#infix_but).
  
  ```raku
  my Int $i = 1 but role :: { method defined { False } };
  say $i // "undefined";
  # OUTPUT: «undefined␤»
  ```
  
  To test for definedness call `.defined`, use [//](/language/operators#infix_//), [with/without](/language/control#with_orwith_without) and [signatures](/language/signatures#Constraining_argument_definiteness).
  
  ### [Coercion](#Type_system "go to top of document")[§](#Coercion "direct link")
  
  Turning one type into another is done with coercion methods that have the same name as the target type. This convention is made mandatory by [Signatures](/language/signatures#Coercion_type). The source type has to know how to turn itself into the target type. To allow built-in types to turn themselves into user defined types use [augment](/language/variables#The_augment_declarator) or the [MOP](/language/mop).
  
  ```raku
  class C {
      has $.int;
      method this-is-c { put 'oi' x $!int ~ '‽' }
  }
  
  use MONKEY-TYPING;
  augment class Int {
      method C { C.new(:int(self))}
  }
  
  my $i = 10;
  $i.=C;
  $i.this-is-c();
  # OUTPUT: «oioioioioioioioioioi‽␤»
  ```
  
  Raku provides methods defined in [`Cool`](/type/Cool) to convert to a target type before applying further operations. Most built-in types descend from [`Cool`](/type/Cool) and as such may provide implicit coercion that may be undesired. It is the responsibility of the user to care about trap-free usage of those methods.
  
  ```raku
  my $whatever = "123.6";
  say $whatever.round;
  # OUTPUT: «124␤»
  say <a b c d>.starts-with("ab");
  # OUTPUT: «False␤»
  ```
  
  # [Type declarators](#Type_system "go to top of document")[§](#Type_declarators "direct link")
  
  Type declarators introduce a new type into the given scope. Nested scopes can be separated by `::`. New [packages](/language/packages) are created automatically if no such scope exists already.
  
  ```raku
  class Foo::Bar::C {};
  put Foo::Bar::.keys;
  # OUTPUT: «C␤»
  ```
  
  Forward declarations can be provided with a block containing only `...`, the ["stub" operator](/language/operators#listop_...). The compiler will check at the end of the current scope if the type is defined.
  
  ```raku
  class C {...}
  # many lines later
  class C { has $.attr }
  ```
  
  ## [`class`](#Type_system "go to top of document")[§](#class "direct link")
  
  The `class` declarator creates a compile time construct that is compiled into a type object. The latter is a simple Raku object and provides methods to construct instances by executing initializers and sub methods to fill all attributes declared in a class, and any parent class, with values. Initializers can be provided with the declaration of attributes or in constructors. It's the responsibility of the [`Metamodel::ClassHOW`](/type/Metamodel/ClassHOW) to know how to run them. This is the only magic part of building objects in Raku. The default parent type is [`Any`](/type/Any), which in turn inherits from [`Mu`](/type/Mu). The latter provides the default constructor `.new` which is named like this by convention. Aside from this, `.new` does not carry any special meaning nor is treated in any special way.
  
  For more information how to use classes see the [Classes and objects](/language/classtut) tutorial.
  
  ### [Mixins](#Type_system "go to top of document")[§](#Mixins "direct link")
  
  The type introduced by `class` can be extended with [infix:<but>](/language/operators#infix_but) at runtime. The original type is not modified, instead a new type object is returned and can be stored in a container that type checks successful against the original type or the role that is mixed in.
  
  ```raku
  class A {}
  role R { method m { say 'oi‽' } }
  my R $A = A but R;
  my $a1 = $A.new;
  $a1.m;
  say [$A ~~ R, $a1 ~~ R];
  # OUTPUT: «oi‽␤[True True]␤»
  ```
  
  ### [Introspection](#Type_system "go to top of document")[§](#Introspection "direct link")
  
  #### [Metaclass](#Type_system "go to top of document")[§](#Metaclass "direct link")
  
  To test if a given type object is a class, test the metaobject method `.HOW` against [`Metamodel::ClassHOW`](/type/Metamodel/ClassHOW).
  
  ```raku
  class C {};
  say C.HOW ~~ Metamodel::ClassHOW;
  # OUTPUT: «True␤»
  ```
  
  ### [Private attributes](#Type_system "go to top of document")[§](#Private_attributes "direct link")
  
  Private [`Attribute`](/type/Attribute)s are addressed with any of the twigils `$!`, `@!` and `%!`. They do not have public accessor methods generated automatically. As such they can not be altered from outside the class they are defined in.
  
  ```raku
  class C {
      has $!priv;
      submethod BUILD { $!priv = 42 }
  };
  
  say (.name, .package, .has_accessor) for C.new.^attributes;
  # OUTPUT: «($!priv (C) False)␤»
  ```
  
  ### [Methods](#Type_system "go to top of document")[§](#Methods "direct link")
  
  The `method` declarator defines objects of type [`Method`](/type/Method) and binds them to the provided name in the scope of a class. Methods in a class are `has` scoped by default. Methods that are `our` scoped are not added to the method cache by default and as such can not be called with the accessor sigil `$.`. Call them with their fully qualified name and the invocant as the first argument.
  
  #### [Inheritance and multis](#Type_system "go to top of document")[§](#Inheritance_and_multis "direct link")
  
  A normal method in a subclass does not compete with multis of a parent class.
  
  ```raku
  class A {
      multi method m(Int $i){ say 'Int' }
      multi method m(int $i){ say 'int' }
  }
  
  class B is A {
      method m(Int $i){ say 'B::Int' }
  }
  
  my int $i;
  B.new.m($i);
  # OUTPUT: «B::Int␤»
  ```
  
  #### [Only method](#Type_system "go to top of document")[§](#Only_method "direct link")
  
  To explicitly state that a method is not a multi method use the `only` method declarator.
  
  ```raku
  class C {
      only method m {};
      multi method m {};
  };
  # OUTPUT: «X::Comp::AdHoc: Cannot have a multi candidate for 'm' when an only method is also in the package 'C'␤»
  
  ```
  
  #### [submethod BUILD](#Type_system "go to top of document")[§](#submethod_BUILD "direct link")
  
  The [submethod](/type/Submethod) `BUILD` is (indirectly) called by [.bless](/type/Mu#method_bless). It is meant to set private and public attributes of a class and receives all named attributes passed into `.bless`. The default constructor [.new](/type/Mu#method_new) defined in [`Mu`](/type/Mu) is the method that invokes it. Given that public accessor methods are not available in `BUILD`, you must use private attribute notation instead.
  
  ```raku
  class C {
      has $.attr;
      submethod BUILD (:$attr = 42) {
          $!attr = $attr
      };
      multi method new($positional) {
          self.bless(:attr($positional), |%_)
     }
  };
  
  C.new.say; C.new('answer').say;
  # OUTPUT: «C.new(attr => 42)␤
  #          C.new(attr => "answer")␤»
  ```
  
  #### [Fallback method](#Type_system "go to top of document")[§](#Fallback_method "direct link")
  
  A method with the special name `FALLBACK` will be called when other means to resolve the name produce no result. The first argument holds the name and all following arguments are forwarded from the original call. Multi methods and [sub-signatures](/language/signatures#Sub-signatures) are supported.
  
  ```raku
  class Magic {
      method FALLBACK ($name, |c(Int, Str)) {
      put "$name called with parameters {c.raku}"  }
  };
  Magic.new.simsalabim(42, "answer");
  
  # OUTPUT: «simsalabim called with parameters ⌈\(42, "answer")⌋␤»
  ```
  
  #### [Reserved method names](#Type_system "go to top of document")[§](#Reserved_method_names "direct link")
  
  Some built-in introspection methods are actually special syntax provided by the compiler, namely `WHAT`, `WHO`, `HOW` and `VAR`. Declaring methods with those names will silently fail. A dynamic call will work, what allows to call methods from foreign objects.
  
  ```raku
  class A {
      method WHAT { "ain't gonna happen" }
  };
  
  say A.new.WHAT;    # OUTPUT: «(A)␤»
  say A.new."WHAT"() # OUTPUT: «ain't gonna happen␤»
  
  ```
  
  #### [Methods in package scope](#Type_system "go to top of document")[§](#Methods_in_package_scope "direct link")
  
  Any `our` scoped method will be visible in the package scope of a class.
  
  ```raku
  class C {
      our method packaged {};
      method loose {}
  };
  say C::.keys
  # OUTPUT: «(&packaged)␤»
  ```
  
  #### [Setting attributes with namesake variables and methods](#Type_system "go to top of document")[§](#Setting_attributes_with_namesake_variables_and_methods "direct link")
  
  Instead of writing `attr => $attr` or `:attr($attr)`, you can save some typing if the variable (or method call) you're setting the attribute with shares the name with the attribute:
  
  ```raku
  class A { has $.i = 42 };
  class B {
      has $.i = "answer";
      method m() { A.new(:$.i) }
      #                  ^^^^  Instead of i => $.i or :i($.i)
  };
  my $a = B.new.m;
  say $a.i; # OUTPUT: «answer␤»
  ```
  
  Since `$.i` method call is named `i` and the attribute is also named `i`, Raku lets us shortcut. The same applies to `:$var`, `:$!private-attribute`, `:&attr-with-code-in-it`, and so on.
  
  ### [trait `is nodal`](#Type_system "go to top of document")[§](#trait_is_nodal "direct link")
  
  Marks a [`List`](/type/List) method to indicate to hyperoperator to not descend into inner [`Iterable`](/type/Iterable)s to call this method. This trait generally isn't something end users would be using, unless they're subclassing or augmenting core [`List`](/type/List) type.
  
  In order to demonstrate the difference consider the following examples, the first using a method (`elems`) that `is nodal` and the second using a method ([`Int`](/type/Int)) which is not nodal.
  
  ```raku
  say ((1.0, "2", 3e0), [^4], '5')».elems; # OUTPUT: «(3, 4, 1)␤»
  say ((1.0, "2", 3e0), [^4], '5')».Int    # OUTPUT: «((1 2 3) [0 1 2 3] 5)␤»
  ```
  
  ### [`handles`](#Type_system "go to top of document")[§](#trait_handles "direct link")
  
  ```raku
  multi trait_mod:<handles>(Attribute:D $target, $thunk)
  ```
  
  The [trait](/type/Sub#Traits) `handles` applied to an attribute of a class will delegate all calls to the provided method name to the method with the same name of the attribute. The object referenced by the attribute must be initialized. A type constraint for the object that the call is delegated to can be provided.
  
  ```raku
  class A      { method m(){ 'A::m has been called.' } }
  class B is A { method m(){ 'B::m has been called.' } }
  class C {
      has A $.delegate handles 'm';
      method new($delegate){ self.bless(delegate => $delegate) }
  };
  say C.new(B.new).m(); # OUTPUT: «B::m has been called.␤»
  ```
  
  Instead of a method name, a [`Pair`](/type/Pair) (for renaming), a list of names or [`Pair`](/type/Pair)s, a [`Regex`](/type/Regex) or a [`Whatever`](/type/Whatever) can be provided. In the latter case existing methods, both in the class itself and its inheritance chain, will take precedence. If even local `FALLBACK`s should be searched, use a [`HyperWhatever`](/type/HyperWhatever).
  
  ```raku
  class A {
      method m1(){ 'A::m1 has been called.' }
      method m2(){ 'A::m2 has been called.' }
  }
  
  class C {
      has $.delegate handles <m1 m2> = A.new()
  }
  say C.new.m2; # OUTPUT: «A::m2 has been called.␤»
  
  class D {
      has $.delegate handles /m\d/ = A.new()
  }
  say D.new.m1; # OUTPUT: «A::m1 has been called.␤»
  
  class E {
      has $.delegate handles (em1 => 'm1') = A.new()
  }
  say E.new.em1; # OUTPUT: «A::m1 has been called.␤»
  
  class F {
    # Delegates all methods from A
    has A $.delegate handles *;
  }
  say F.new.m1; # OUTPUT: «A::m1 has been called.␤»
  say F.new.m2; # OUTPUT: «A::m2 has been called.␤»
  ```
  
  ### [trait `is`](#Type_system "go to top of document")[§](#trait_is "direct link")
  
  ```raku
  multi trait_mod:<is>(Mu:U $child, Mu:U $parent)
  ```
  
  The [trait](/type/Sub#Traits) `is` accepts a type object to be added as a parent class of a class in its definition. To allow multiple inheritance the trait can be applied more than once. Adding parents to a class will import their methods into the target class. If the same method name occurs in multiple parents, the first added parent will win.
  
  If no `is` trait is provided the default of [`Any`](/type/Any) will be used as a parent class. This forces all Raku objects to have the same set of basic methods to provide an interface for introspection and coercion to basic types.
  
  ```raku
  class A {
      multi method from-a(){ 'A::from-a' }
  }
  say A.new.^parents(:all).raku;
  # OUTPUT: «(Any, Mu)␤»
  
  class B {
      method from-b(){ 'B::from-b ' }
      multi method from-a(){ 'B::from-A' }
  }
  
  class C is A is B {}
  say C.new.from-a();
  # OUTPUT: «A::from-a␤»
  ```
  
  ### [`is rw`](#Type_system "go to top of document")[§](#trait_is_rw "direct link")
  
  ```raku
  sub trait_mod:<is>(Mu:U $type, :$rw!)
  ```
  
  The [trait](/type/Sub#Traits) `is rw` on a class will create writable accessor methods on all public attributes of that class.
  
  ```raku
  class C is rw {
      has $.a;
  };
  my $c = C.new.a = 42;
  say $c; # OUTPUT: «42␤»
  ```
  
  ### [trait `is required`](#Type_system "go to top of document")[§](#trait_is_required "direct link")
  
  ```raku
  multi trait_mod:<is>(Attribute $attr, :$required!)
  multi trait_mod:<is>(Parameter:D $param, :$required!)
  ```
  
  Marks a class or roles attribute as required. If the attribute is not initialized at object construction time throws [`X::Attribute::Required`](/type/X/Attribute/Required).
  
  ```raku
  class Correct {
      has $.attr is required;
  }
  say Correct.new(attr => 42);
  # OUTPUT: «Correct.new(attr => 42)␤»
  
  class C {
      has $.attr is required;
  }
  C.new;
  CATCH { default { say .^name => .Str } }
  # OUTPUT: «X::Attribute::Required => The attribute '$!attr' is required, but you did not provide a value for it.␤»
  ```
  
  Note a class with a private attribute will give the same error:
  
  ```raku
  class D {
      has $!attr is required;
  }
  D.new;
  CATCH { default { say .^name => .Str } }
  # OUTPUT: «X::Attribute::Required => The attribute '$!attr' is required, but you did not provide a value for it.␤»
  ```
  
  You can provide a reason why it's required as an argument to `is required`
  
  ```raku
  class Correct {
      has $.attr is required("it's so cool")
  };
  say Correct.new();
  # OUTPUT: «The attribute '$!attr' is required because it's so cool,␤but you did not provide a value for it.␤»
  
  ```
  
  ### [trait `hides`](#Type_system "go to top of document")[§](#trait_hides "direct link")
  
  The trait `hides` provides inheritance without being subject to [re-dispatching](/language/functions#Re-dispatching).
  
  ```raku
  class A {
      method m { say 'i am hidden' }
  }
  class B hides A {
      method m { nextsame }
      method n { self.A::m }
  };
  
  B.new.m;  # No output
  B.new.n;  # OUTPUT: «i am hidden␤»
  ```
  
  The trait `is hidden` allows a class to hide itself from [re-dispatching](/language/functions#Re-dispatching).
  
  ```raku
  class A is hidden {
      method m { say 'i am hidden' }
  }
  class B is A {
      method m { nextsame }
      method n { self.A::m }
  }
  
  B.new.m; # No output
  B.new.n; # OUTPUT: «i am hidden␤»
  ```
  
  Classes declared with `is hidden` also generate slightly different method signatures. To facilitate re-dispatch, typical methods are automatically provided with an extra `*%_` parameter that [captures extra named arguments](/type/Method#index-entry-*%___(extra_named_arguments)). Because classes declared with `is hidden` don't participate in re-dispatch, their methods don't receive this extra parameter.
  
  ### [trait `trusts`](#Type_system "go to top of document")[§](#trait_trusts "direct link")
  
  To allow one class to access the private methods of another class use the trait `trusts`. A forward declaration of the trusted class may be required.
  
  ```raku
  class B {...};
  class A {
      trusts B;
      has $!foo;
      method !foo { return-rw $!foo }
      method raku { "A.new(foo => $!foo)" }
  };
  class B {
      has A $.a .= new;
      method change { $!a!A::foo = 42; self }
  };
  say B.new.change;
  # OUTPUT: «B.new(a => A.new(foo => 42))␤»
  ```
  
  ### [Augmenting a class](#Type_system "go to top of document")[§](#Augmenting_a_class "direct link")
  
  To add methods and attributes to a class at compile time use `augment` in front of a class definition fragment. The compiler will demand the pragmas `use MONKEY-TYPING` or `use MONKEY` early in the same scope. Please note that there may be performance implications, hence the pragmas.
  
  ```raku
  use MONKEY; augment class Str {
      method mark(Any :$set){
          state $mark //= $set; $mark
      }
  };
  my $s = "42";
  $s.mark(set => "answer");
  say $s.mark
  # OUTPUT: «answer␤»
  ```
  
  There are few limitations of what can be done inside the class fragment. One of them is the redeclaration of a method or sub into a multi. Using added attributes is not implemented. Please note that adding a multi candidate that differs only in its named parameters will add that candidate behind the already defined one and as such it won't be picked by the dispatcher.
  
  ## [`role`](#Type_system "go to top of document")[§](#role "direct link")
  
  Roles are class fragments, which allow the definition of interfaces that are shared by classes. The `role` declarator also introduces a type object that can be used for type checks. Roles can be mixed into classes and objects at runtime and compile time. The `role` declarator returns the created type object thus allowing the definition of anonymous roles and in-place mixins.
  
  ```raku
  role Serialize {
      method to-string { self.Str }
      method to-number { self.Num }
  }
  
  class A does Serialize {}
  class B does Serialize {}
  
  my Serialize @list;
  @list.push: A.new;
  @list.push: B.new;
  
  say @list».to-string;
  # OUTPUT: «[A<57192848> B<57192880>]␤»
  ```
  
  Use `...` as the only element of a method body to declare a method to be abstract. Any class getting such a method mixed in has to overload it. If the method is not overloaded before the end of the compilation unit [`X::Comp::AdHoc`](/type/X/Comp/AdHoc) will be thrown.
  
  ```raku
  EVAL 'role R { method overload-this(){...} }; class A does R {}; ';
  CATCH { default { say .^name, ' ', .Str } }
  # OUTPUT: «X::Comp::AdHoc Method 'overload-this' must be implemented by A because it is required by roles: R.␤»
  ```
  
  ### [Auto-punning](#Type_system "go to top of document")[§](#Auto-punning "direct link")
  
  A role can be used instead of a class to create objects. Since roles can't exist at runtime, a class of the same name is created that will type check successful against the role.
  
  ```raku
  role R { method m { say 'oi‽' } };
  R.new.^mro.say;
  # OUTPUT: «((R) (Any) (Mu))␤»
  say R.new.^mro[0].HOW.^name;
  # OUTPUT: «Perl6::Metamodel::ClassHOW␤»
  say R.new ~~ R;
  # OUTPUT: «True␤»
  ```
  
  ### [trait `does`](#Type_system "go to top of document")[§](#trait_does "direct link")
  
  The trait `does` can be applied to roles and classes providing compile time mixins. To refer to a role that is not defined yet, use a forward declaration. The type name of the class with mixed in roles does not reflect the mixin, a type check does. If methods are provided in more than one mixed in role, the method that is defined first takes precedence. A list of roles separated by comma can be provided. In this case conflicts will be reported at compile time.
  
  ```raku
  role R2 {...};
  role R1 does R2 {};
  role R2 {};
  class C does R1 {};
  
  say [C ~~ R1, C ~~ R2];
  # OUTPUT: «[True True]␤»
  ```
  
  For runtime mixins see [but](/language/operators#infix_but) and [does](/language/operators#infix_does).
  
  ### [Parameterized](#Type_system "go to top of document")[§](#Parameterized "direct link")
  
  Roles can be provided with parameters in-between `[]` behind a roles name. [Type captures](/language/signatures#Type_captures) are supported.
  
  ```raku
  role R[$d] { has $.a = $d };
  class C does R["default"] { };
  
  my $c = C.new;
  say $c;
  # OUTPUT: «C.new(a => "default")␤»
  ```
  
  Parameters can have type constraints, `where` clauses are not supported for types but can be implemented via [`subset`s](#subset).
  
  ```raku
  class A {};
  class B {};
  subset A-or-B where * ~~ A|B;
  role R[A-or-B ::T] {};
  R[A.new].new;
  ```
  
  Default parameters can be provided.
  
  ```raku
  role R[$p = fail("Please provide a parameter to role R")] {};
  my $i = 1 does R;
  CATCH { default { say .^name, ': ', .Str} }
  # OUTPUT: «X::AdHoc: Could not instantiate role 'R':␤Please provide a parameter to role R␤»
  ```
  
  ### [As type constraints](#Type_system "go to top of document")[§](#As_type_constraints "direct link")
  
  Roles can be used as type constraints wherever a type is expected. If a role is mixed in with `does` or `but`, its type-object is added to the type-object list of the object in question. If a role is used instead of a class (using auto-punning), the auto-generated class' type-object, of the same name as the role, is added to the inheritance chain.
  
  ```raku
  role Unitish[$unit = fail('Please provide a SI unit quantifier as a parameter to the role Unitish')] {
      has $.SI-unit-symbol = $unit;
      method gist {
          given self {
              # ...
              when * < 1 { return self * 1000 ~ 'm' ~ $.SI-unit-symbol }
              when * < 1000 { return self ~ $.SI-unit-symbol }
              when * < 1_000_000 { return self / 1_000 ~ 'k' ~ $.SI-unit-symbol }
              # ...
          }
      }
  }
  
  role SI-second   does Unitish[<s>] {}
  role SI-meter    does Unitish[<m>] {}
  role SI-kilogram does Unitish[<g>] {}
  
  sub postfix:<s>(Numeric $num) { ($num) does SI-second }
  sub postfix:<m>(Numeric $num) { ($num) does SI-meter }
  sub postfix:<g>(Numeric $num) { ($num) does SI-kilogram }
  sub postfix:<kg>(Numeric $num){ ($num * 1000) does SI-kilogram }
  
  constant g = 9.806_65;
  
  role SI-Newton does Unitish[<N>] {}
  
  multi N(SI-kilogram $kg, SI-meter $m, SI-second $s --> SI-Newton ){ ($kg * ($m / $s²)) does SI-Newton }
  multi N(SI-kilogram $kg --> SI-Newton)                            { ($kg * g) does SI-Newton }
  
  say [75kg, N(75kg)];
  # OUTPUT: «[75kg 735.49875kN]␤»
  say [(75kg).^name, N(75kg).^name];
  # OUTPUT: «[Int+{SI-kilogram} Rat+{SI-Newton}]␤»
  
  ```
  
  ## [`enum`](#Type_system "go to top of document")[§](#enum "direct link")
  
  Enumerations provide constant key-value-pairs with an associated type. Any key is of that type and injected as a symbol into the current scope. If the symbol is used, it is treated as a constant expression and the symbol is replaced with the value of the enum-pair. Any Enumeration inherits methods from the role [`Enumeration`](/type/Enumeration). Complex expressions for generating key-value pairs are not supported. In general, an `enum` is a [`Map`](/type/Map) whose elements have the [`Enumeration`](/type/Enumeration) role mixed in; this role includes, for each element, an index which creates an order on the map.
  
  Stringification of the symbol, which is done automatically in string context and is exactly equal to its name, which is also the key of the enum-pair.
  
  ```raku
  enum Names ( name1 => 1, name2 => 2 );
  say name1, ' ', name2; # OUTPUT: «name1 name2␤»
  say name1.value, ' ', name2.value; # OUTPUT: «1 2␤»
  ```
  
  Comparing symbols will use type information and the value of the enum-pair. As value types [`Num`](/type/Num) and [`Str`](/type/Str) are supported.
  
  ```raku
  enum Names ( name1 => 1, name2 => 2 );
  sub same(Names $a, Names $b){
     $a eqv $b
  }
  
  say same(name1, name1); # OUTPUT: «True␤»
  say same(name1, name2); # OUTPUT: «False␤»
  my $a = name1;
  say $a ~~ Names; # OUTPUT: «True␤»
  say $a.^name;    # OUTPUT: «Names␤»
  ```
  
  All keys have to be of the same type.
  
  ```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))␤»
  ```
  
  And you can use any kind of symbol:
  
  ```raku
  enum Suit <♣ ♦ ♥ ♠>;
  ```
  
  As long as you refer to that symbol using the full syntax:
  
  ```raku
  say Suit::<♣>; # OUTPUT: «♣␤»
  my $heart = '♥';
  say Suit::«$heart»; # OUTPUT: «♥␤»
  
  ```
  
  Attempting to access unicode enum keys without said syntax will result in an error:
  
  ```raku
  say ♣ ; # OUTPUT: «(exit code 1) ===SORRY!===␤Argument to "say" seems to be malformed…
  
  ```
  
  If no value is given [`Int`](/type/Int) will be assumed as the values type and incremented by one per key starting at zero. As enum key types [`Int`](/type/Int), [`Num`](/type/Num), [`Rat`](/type/Rat) and [`Str`](/type/Str) are supported.
  
  ```raku
  enum Numbers <one two three four>;
  
  say Numbers.enums;
  # OUTPUT: «Map.new((four => 3, one => 0, three => 2, two => 1))␤»
  ```
  
  A different starting value can be provided.
  
  ```raku
  enum Numbers «:one(1) two three four»;
  
  say Numbers.enums;
  # OUTPUT: «Map.new((four => 4, one => 1, three => 3, two => 2))␤»
  ```
  
  You can also do this with the **()** form of the initializer, but will need to quote keys that do not have a value:
  
  ```raku
  enum Numbers (
    one => 1,
    'two',
    'three',
    'four'
  );
  ```
  
  Enums can also be anonymous, with the only difference with named `enum`s being that you cannot use it in [`Signature`](/type/Signature)s or to declare variables.
  
  ```raku
  my $e = enum <one two three>;
  say two;       # OUTPUT: «two␤»
  say one.^name; # OUTPUT: «␤»
  say $e.^name;  # OUTPUT: «Map␤»
  ```
  
  There are various methods to get access to the keys and values of the symbols that have been defined. All of them turn the values into [`Str`](/type/Str), which may not be desirable. By treating the enum as a package, we can get a list of types for the keys.
  
  ```raku
  enum E <one two>;
  my @keys = E::.values;
  say @keys.map: *.raku;
  # OUTPUT: «(E::one E::two)␤» or «(E::two E::one)␤»
  ```
  
  Note that, as the output above indicates, the iteration order of enums is not guaranteed. This is because the methods that "iterate over" an enum do not iterate *directly* on the enum (which, after all, is not iterable). Instead, these iteration methods create a [`Map`](/type/Map) with the same keys and values as the enum. Because [`Map`](/type/Map)s provide only unordered, iteration the iteration methods on an enum do as well. If you need to iterate an enum in order, you can sort on its `value`, for example with `E.enums.sort(*.value)`.
  
  With the use of **()** parentheses, an enum can be defined using any arbitrary dynamically defined list. The list should consist of Pair objects:
  
  For example, in file `config` we have:
  
  ｢text｣ without highlighting
  
  ```
  
  
  ```
  
  a 1
  b 2
  
  
  ```
  
  
  ```
  
  We can create an enum using it with this code:
  
  ```raku
  enum ConfigValues ('config'.IO.lines.map({ my ($key, $value) = $_.words