@@ -906,43 +906,51 @@ say LoggedVersion.new('1.0.2');
906
906
907
907
= head1 Coercion Types
908
908
909
- Coercion types can help you to have a specific type inside a routine, but
910
- accept wider input. When the routine is called, the argument is automatically
911
- converted to the narrower type.
909
+ Coercion types force a specific type for routine arguments while allowing
910
+ the routine itself to accept a wider input. When invoked, the arguments are
911
+ narrowed automatically to the stricter type, and therefore within the routine
912
+ the arguments have always the desired type.
913
+
914
+ In the case the arguments cannot be converted to the stricter type, a I < Type Check > error
915
+ is thrown.
912
916
913
917
= begin code
914
918
sub double(Int(Cool) $x) {
915
919
2 * $x
916
920
}
917
921
918
922
say double '21'; # OUTPUT: «42»
923
+ say double 21; # OUTPUT: «42»
919
924
say double Any; # Type check failed in binding $x; expected 'Cool' but got 'Any'
920
925
= end code
921
926
922
- Here , the C < Int > is the target type to which the argument will be coerced, and
923
- C < Cool > is the type that the routine accepts as input.
927
+ In the above example , the L < Int|/type/Int > is the target type to which the argument C < $x > will be coerced, and
928
+ L < Cool|/type/Cool > is the type that the routine accepts as wider input.
924
929
925
- If the accepted input type is L < Any|/type/Any > , you can abbreviate C < Int(Any) >
926
- to C < Int() > .
930
+ If the accepted wider input type is L < Any|/type/Any > , it is possible to abbreviate the coercion C < Int(Any) >
931
+ omitting the C < Any > type, thus resulting in C < Int() > .
927
932
928
933
The coercion works by looking for a method with the same name
929
- as the target type. You can define coercions for your own types like so:
934
+ as the target type: if such method is found on the argument, it is invoked to
935
+ convert the latter to the expected narrow type.
936
+ From the above, it is clear that it is possible to provide coercion among user types
937
+ just providing the required methods:
930
938
931
939
= begin code
932
- class Bar {...}
940
+ class Bar {
941
+ has $.msg;
942
+ }
933
943
934
944
class Foo {
935
945
has $.msg = "I'm a foo!";
936
946
947
+ # allows coercion from Foo to Bar
937
948
method Bar {
938
949
Bar.new(:msg($.msg ~ ' But I am now Bar.'));
939
950
}
940
951
}
941
952
942
- class Bar {
943
- has $.msg;
944
- }
945
-
953
+ # wants a Bar, but accepts Any
946
954
sub print-bar(Bar() $bar) {
947
955
say $bar.^name; # OUTPUT: «Bar»
948
956
say $bar.msg; # OUTPUT: «I'm a foo! But I am now Bar.»
@@ -951,9 +959,15 @@ sub print-bar(Bar() $bar) {
951
959
print-bar Foo.new;
952
960
= end code
953
961
962
+ In the above code, once a C < Foo > instance is passed as argument to C < print-bar > , the C < Foo.Bar >
963
+ method is called and the result is placed into C < $bar > .
964
+
954
965
Coercion types are supposed to work wherever types work, but Rakudo currently
955
966
(2017.05) only implements them in signatures, for both parameters and return types.
956
967
968
+ = comment is the above referencing rakudo 2017.05 still valid?
969
+ = comment is it worth placing an example about return types?
970
+
957
971
= head1 sub MAIN
958
972
959
973
X < |MAIN > X < |command line arguments >
0 commit comments