In Control flow§
See primary documentation in context for with orwith without
The with
statement is like if
, but tests for definedness rather than truth, and it topicalizes on the condition, much like given
:
with "abc".index("a") { .say } # prints 0
Similarly to elsif
, orwith
may be used to chain definedness tests:
# The below code says "Found 'a' at 0" my $s = "abc"; with $s.index("a") { say "Found 'a' at $_" } orwith $s.index("b") { say "Found 'b' at $_" } orwith $s.index("c") { say "Found 'c' at $_" } else { say "Didn't find 'a', 'b' or 'c'" }
You may intermix if
-based and with
-based clauses.
# This says "Yes" if 0 { say "No" } orwith Nil { say "No" } orwith 0 { say "Yes" };
As with unless
, you may use without
to check for undefinedness, but you may not add an else
clause:
my $answer = Any; without $answer { warn "Got: {$_.raku}" }
There are also with
and without
statement modifiers:
my $answer = (Any, True).roll; say 42 with $answer; warn "undefined answer" without $answer;
As with the other chainable constructs, an else
completing a with/if
..orwith/elsif
chain will itself topicalize to the value of the prior (failed) condition's topic (either the topic of with
or the final orwith
or elsif
).
In the case of an else
following a with
or orwith
, topicalizing a value guaranteed to be undefined may seem useless. But it makes for a useful idiom when used in conjunction with operations that may fail, because Failure
values are always undefined:
sub may_fail( --> Numeric:D ) { my $value = (^10).pick || fail "Zero is unacceptable"; fail "Odd is also not okay" if $value % 2; return $value; } with may_fail() -> $value { # defined, so didn't fail say "I know $value isn't zero or odd." } else { # undefined, so failed, and the Failure is the topic say "Uh-oh: {.exception.message}." }
Note that while topicalizing a Failure
marks it handled
—so you can use the with
/else
to proceed safely with execution—it doesn't make the Failure value itself safe. Even within the else
clause, if you try to use the value directly, it will result in your else
clause itself failing (or, in Rakudo, "promoting" the Failure into a thrown exception).
But as seen above, you can use the methods of a handled Failure
object the else
topicalizes, such as exception
, if you wish to provide diagnostics or interrogate the underlying Exception
.