@@ -133,6 +133,10 @@ change the variable name it is bound to.
133
133
}
134
134
say Foo.whoami; # OUTPUT: «Well I'm class Foo, of course!»
135
135
136
+ A further exception is the L<double semicolon C<;;>|/language/Signatures#The_;;_separator>,
137
+ which can be used in L<multi|/language/functions#Multi-dispatch> signatures to declare that all subsequent parameters should not
138
+ contribute to its precedence under multiple dispatch.
139
+
136
140
X<|Language,type constraint>
137
141
X<|Language,Constraint>
138
142
=head1 Type constraints
@@ -1125,14 +1129,52 @@ indicate that the routine's L<C<multi> definitions|/syntax/multi> can have any L
1125
1129
constraints|#Type_constraints>. See L<proto|/language/functions#proto> for an
1126
1130
example.
1127
1131
1128
- =head1 X<Long names|Language,Long names>
1132
+ =head1 X<The C«;;» separator|Syntax,double-semicolon;Language,Long names>
1133
+
1134
+ In L<multiple dispatch|/language/Functions#Multi-dispatch>, when more than one multi signature matches
1135
+ the given input parameters, the narrowest signature wins.
1136
+
1137
+ When a double semicolon C<;;> is present in a signature,
1138
+ only parameters to the left of the C<;;> are considered in this narrowness analysis.
1139
+ It can take the place of a comma, or be at the very beginning:
1140
+
1141
+ multi foo (;; Numeric $a) { say "numeric" };
1142
+ multi foo (;; Int $a) { say "int" };
1143
+ foo(42);
1144
+ # OUTPUT: «Ambiguous call to 'foo(Int)'; these signatures all match:
1145
+ # (;; Numeric $a) from <unknown file> line 1
1146
+ # (;; Int $a) from <unknown file> line 1...»
1147
+ # (Without the ;; the output would have been «int».)
1148
+
1149
+ This can be useful when the usual order of precedence is undesired.
1150
+ Consider this example with a named parameter:
1151
+
1152
+ multi bar(Int $i) { say "just $i" };
1153
+ multi bar(Int $i, Str :$s) { say "both $i and 「$s.raku」" };
1154
+ bar(42);
1155
+ # OUTPUT: «Use of uninitialized value of type Str in string context.(...)
1156
+ # both 42 and 「」 in sub e at <tmp> line 1»
1157
+
1158
+ Here it was the I<second> multi that got executed,
1159
+ because its signature is narrower than the first and does in fact match C<bar(42)>, even though $s then stays undefined.
1160
+ By adding C<;;>, we can lower its precedence:
1161
+
1162
+ multi f(Int $i) { say "just $i" };
1163
+ multi f(Int $i;; Str :$s) { say "both $i and 「$s」" };
1164
+ f(42);
1165
+ # OUTPUT: «Ambiguous call to 'e(Int)'; these signatures all match:
1166
+ # (Int $i) from <tmp> line 1 (Int $i;; Str :$s) from <tmp> line 1 ...»
1167
+
1168
+ One could then give the first multi the trait L<C<is default>|/type/Routine#trait_is_default>, whose exact effect is
1169
+ to break a tie between multiple signatures of the same precedence.
1129
1170
1130
- To exclude certain parameters from being considered in multiple dispatch,
1131
- separate them with a double semicolon.
1171
+ There is more than one way to control the narrowness
1172
+ (and thereby, precedence) of signatures. Other options include
1173
+ making parameters optional via C<?> or required via C<!>.
1132
1174
1133
- multi f(Int $i, Str $s;; :$b) { say "$i, $s, {$b.raku}" };
1134
- f(10, 'answer');
1135
- # OUTPUT: «10, answer, Any»
1175
+ The double semicolon C<;;> can also be used in signatures of L<parameterized Roles|/language/Typesystem#Parameterized>.
1176
+ Parameterized roles have a so-called "long name" generated from their signature, which can be used for introspection.
1177
+ Only parameters to the left of C<;;> contribute to it.
1136
1178
1137
1179
=head1 Parameter traits and modifiers
1138
1180
0 commit comments