Documentation for syntax proto
assembled from the following pages:
Language documentation: Functions §
From Functions
(Functions) Syntax proto 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'); # OK congratulate('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 unsuccessful proto 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」