In Functions§
See primary documentation in context 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:
proto congratulate(Str , Str , |)multi congratulate(, )multi congratulate(, , Int )congratulate('being a cool number', 'Fred'); # OKcongratulate('being a cool number', 'Fred', 42); # OK
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
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
.
say .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:
# attempts to notify someone -- False if unsuccessfulproto notify(Str , Str )
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:
<LOG WARNING ERROR>;proto debug(DebugType , Str --> Bool)multi debug(LOG;; Str --> 32)multi debug(WARNING;; Str --> 33)multi debug(ERROR;; Str --> 31)
{*}
always dispatches to candidates with the parameters it's called with. Parameter defaults and type coercions will work but are not passed on.
proto mistake-proto(Str() , Int = 42)multi mistake-proto(, )mistake-proto(7, 42); # OUTPUT: «Int» -- not passed on
mistake-proto('test'); # fails -- not passed on
A longer example using proto
for methods shows how to extract common functionality into a proto method.
my NewClass .= new;.handle('hello world');.handle(<hello world>);.debug = True;.handle('hello world');.handle(<hello world>);.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」