NAME
PerlX::SafeNav - Safe-navigation for Perl
SYNOPSIS
Wrap a chain of method calls to make it resilient on encountering undef
values in the middle:
use PerlX::SafeNav ('$safenav', '$unsafenav', 'safenav');
my $answer = safenav {
$_->a()->{b}->c()->[42]->d()
} $o;
my $tire_age = $car -> $safenav
-> wheels()
-> [0] # undef, if no wheels at all.
-> tire() # undef, if no tire on the wheel.
-> {created_on}
-> delta_days($now)
-> $unsafenav;
unless (defined $tire_age) {
# The car either have no wheels, or the first wheel has no tire.
...
}
DESCRIPTION
Background
In many other languages, there is an operator (often ?.
) doing "Safe navigation", or "Optional Chaining". The operator does a method-call when its left-hand side (first operant) is an object. But when the left-hand side is an undefined value (or null value), the operator returns but evaluates to undef
.
For perl there is currently an PPC: Optional Chaining
This module provides a mean of making chains of method call safe regarding undef values. When encountering an undef
in the middle of a call chain like $o->foo()->bar()->baz()
, the program would die with a message like this:
Can't call method "bar" on an undefined value
With the help of this module, instead of making the program die, the call chain is reduced to undef
.
Usages
$safenav
and $unsafenav
With this module, instead of using a different operator, we wrap a chain of calls to make it safe with the imported $safenav
and $unsafenav
. $safenav
must be placed at the beginning, while $unsafenav
must be place at the end. The should be invoked as method calls, like this:
$obj-> $safenav
-> a()
-> {b}
-> [0]
-> c()
-> $unsafenav;
Notice that it is possible to mix all three kinds method calls, hash fetches, and array fetches together in the same chain. If any of the 4 sub-expresions returns undef
, the entire chain upto $unsafenav
would also be evaluated to undef
. (For this reason, you probably don't want to concatenate more sub-expressions after $unsafenav
.)
This module provide 2 symbols are both $
-sigiled scalar variables, this is on purpose, so that they could be called as methods on arbitrary scalar values.
It is mandatory to have both $safenav
and $unsafenav
together in the same chain. Without $unsafenav
, the original return value of the chain would be forever wrapped inside the mechanism of PerlX::SafeNav
.
While being unconventional in their look, one benifit is that the chance of having naming conflicts with methods from $o
should be very small. However, be aware that $safenav
and $unsafenav
would be masked by locally-defined variables with the same name.
safenav block
A block syntax is also provided by importing the safenav
symbol explicitly:
use PerlX::SafeNav ('safenav');
my $answer = safenav {
$_ ->a()->{b}->[0]->c()
} $o;
Inside this safenav
block, $_
is the safenav-wrapped version of $o
, and the chain is automaticly un-wrapped at the end. $answer
contains the return value of method c()
if no undef
values are encountered or otherwise, an undef
.
Bugs
There are likely many unknown bugs, as the current test suite only covers the minmum set of forms that are known to work.
AUTHOR
Kang-min Liu <gugod@gugod.org>
Toby Inkster <tobyink@cpan.org>
COPYRIGHT AND LICENSE
Copyright (c) 2023 Kang-min Liu <gugod@gugod.org>
.
This is free software, licensed under:
The MIT License
DISCLAIMER OF WARRANTY
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.