-
Notifications
You must be signed in to change notification settings - Fork 292
/
Failure.pod6
121 lines (77 loc) · 3.17 KB
/
Failure.pod6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
=begin pod
=TITLE class Failure
=SUBTITLE Delayed exception
class Failure { }
A C<Failure> is a I<soft> or I<unthrown> exception, usually generated by
calling C<&fail>. It acts as a wrapper around an L<Exception> object.
Sink (void) context causes a Failure to throw, i.e. turn into a normal
exception.
Checking a Failure for truth (with the C<Bool> method) or definedness (with
the C<defined> method) marks the failure as handled, and causes it not to
throw in sink context anymore.
You can call the C<handled> method to check if a failure has been handled.
Calling methods on unhandled failures propagates the failure. The
specification says the result is another C<Failure>, in Rakudo it causes the
failure to throw.
=head1 Methods
=head mothod new
Defined as:
method new(Failure:D: $payload --> Failure)
Returns a new C<Failure> instance with the given payload. The latter can be
either an C<Exception> or a payload for an C<Exception>. A typical payload
would be a C<Str> with an error message. A list of payloads is also excepted.
my $e = Failure.new(now.DateTime, 'WELP‼');
say $e;
CATCH{ default { say .^name, ': ', .Str } }
# OUTPUT: «X::AdHoc: 2017-09-10T11:56:05.477237ZWELP‼»
=head2 method handled
Defined as:
method handled(Failure:D: --> Bool:D)
Returns C<True> for handled failures, C<False> otherwise.
sub f() { fail }; my $v = f; say $v.handled; # OUTPUT: «False»
The C<handled> method is an lvalue, which means you can also use it to set the
handled state:
sub f() { fail }
my $v = f;
$v.handled = True;
say $v.handled; # OUTPUT: «True»
=head2 method exception
Defined as:
method exception(Failure:D: --> Exception)
Returns the L<Exception> object that the failure wraps.
sub failer() { fail };
my $failure = failer;
my $ex = $failure.exception;
put "$ex.^name(): $ex";
# OUTPUT: «X::AdHoc: Failed»
=head2 method self
Defined as:
method exception(Failure:D: --> Failure:D)
If the invocant is a L<handled> C<Failure>, returns it as is.
If not handled, throws its L<Exception>. Since
L<Mu> type L«provides C<.self>|/type/Mu#method_self» for every
class, calling this method is a handy way to explosively
filter out Failures:
my $num1 = '♥'.Int;
# $num1 now contains a Failure object, which may not be desirable
my $num2 = '♥'.Int.self;
# .self method call on Failure causes an exception to be thrown
my $num3 = '42'.Int.self;
# Int type has a .self method, so here $num3 has `42` in it
(my $stuff = '♥'.Int).so;
say $stuff.self; # OUTPUT: «(HANDLED) Cannot convert string to number…»
# Here, Failure is handled, so .self just returns it as is
=head2 method Bool
Defined as:
multi method Bool(Failure:D: --> Bool:D)
Returns C<False>, and marks the failure as handled.
sub f() { fail }; my $v = f; say $v.handled; $v.Bool; say $v.handled;
# OUTPUT: «False
# True»
=head2 method defined
Defined as:
multi method defined(Failure:D: --> Bool:D)
Returns C<False> (failures are officially undefined), and marks
the failure as handled.
sub f() { fail }; my $v = f; say $v.defined; # OUTPUT: «False»
=end pod