txt: ## proto.md
  proto
  
  Combined from primary sources listed below.
  
  # [In Functions](#___top "go to top of document")[§](#(Functions)_proto_proto "direct link")
  
  See primary documentation
  [in context](/language/functions#proto)
  for **proto**.
  
  `proto` is a way to formally declare commonalities between `multi` candidates. It acts as a wrapper that can validate but not modify arguments. Consider this basic example:
  
  ```raku
  proto congratulate(Str $reason, Str $name, |) {*}
  multi congratulate($reason, $name) {
     say "Hooray for your $reason, $name";
  }
  multi congratulate($reason, $name, Int $rank) {
     say "Hooray for your $reason, $name -- got rank $rank!";
  }
  
  congratulate('being a cool number', 'Fred');     # OK
  congratulate('being a cool number', 'Fred', 42); # OK
  ```
  
  ```raku
  congratulate('being a cool number', 42);         # Proto match error
  
  ```
  
  The proto insists that all `multi congratulate` subs conform to the basic signature of two strings, optionally followed by further parameters. The `|` is an un-named [`Capture`](/type/Capture) parameter, and allows a `multi` to take additional arguments. The first two calls succeed, but the third fails (at compile time) because `42` doesn't match [`Str`](/type/Str).
  
  ```raku
  say &congratulate.signature # OUTPUT: «(Str $reason, Str $name, | is raw)␤»
  
  ```
  
  You can give the `proto` a function body, and place the `{*}` (note there is no whitespace inside the curly braces) where you want the dispatch to be done. This can be useful when you have a "hole" in your routine that gives it different behavior depending on the arguments given:
  
  ```raku
  # attempts to notify someone -- False if unsuccessful
  proto notify(Str $user, Str $msg) {
     my \hour = DateTime.now.hour;
     if 8 < hour < 22 {
        return {*};
     } else {
        # we can't notify someone when they might be sleeping
        return False;
     }
  }
  ```
  
  Since `proto` is a wrapper for `multi` candidates, the signatures of the routine's `multi` candidates do not necessarily have to match that of the `proto`; arguments of `multi` candidates may have subtypes of those of the `proto`, and the return types of the `multi` candidates may be entirely different from that of the `proto`. Using differing types like this is especially useful when giving `proto` a function body:
  
  ```raku
  enum DebugType <LOG WARNING ERROR>;
  
  #|[ Prints a message to stderr with a color-coded key. ]
  proto debug(DebugType:D $type, Str:D $message --> Bool:_) {
      note sprintf qb/\e[1;%dm[%s]\e[0m %s/, {*}, $type.key, $message
  }
  multi debug(LOG;; Str:D --> 32)     { }
  multi debug(WARNING;; Str:D --> 33) { }
  multi debug(ERROR;; Str:D --> 31)   { }
  
  ```
  
  `{*}` always dispatches to candidates with the parameters it's called with. Parameter defaults and type coercions will work but are not passed on.
  
  ```raku
  proto mistake-proto(Str() $str, Int $number = 42) {*}
  multi mistake-proto($str, $number) { say $str.^name }
  mistake-proto(7, 42);  # OUTPUT: «Int␤» -- not passed on
  
  ```
  
  ```raku
  mistake-proto('test'); # fails -- not passed on
  
  ```
  
  A longer example using `proto` for methods shows how to extract common functionality into a proto method.
  
  ```raku
  class NewClass {
      has $.debug is rw = False;
      has $.value is rw = 'Initial value';
      proto method handle( | ) {
          note "before value is ｢$.value｣" if $.debug;
          {*}
          note "after value is ｢$.value｣" if $.debug;
      }
      multi method handle(Str $s) {
          $.value = $s;
          say 'in string'
      }
      multi method handle(Positional $s) {
          $.value = $s[0];
          say 'in positional'
      }
      multi method handle( $a, $b ) {
          $.value = "$a is looking askance at $b";
          say 'with more than one value'
      }
  }
  my NewClass $x .= new;
  $x.handle('hello world');
  $x.handle(<hello world>);
  $x.debug = True;
  $x.handle('hello world');
  $x.handle(<hello world>);
  $x.handle('Claire', 'John');
  # OUTPUT:
  # in string
  # in positional
  # before value is ｢hello｣
  # in string
  # after value is ｢hello world｣
  # before value is ｢hello world｣
  # in positional
  # after value is ｢hello｣
  # before value is ｢hello｣
  # with more than one value
  # after value is ｢Claire is looking askance at John｣
  
  ```
  