Error::ROP - A simple and lightweight implementation error handling library for Perl, inspired in the Rop type.
use Error::ROP qw(rop); my $meaning = rop { 80 / $divisor }->then(sub { $_ + 2 }); say "The life meaning is " . $meaning->value if $meaning->is_valid; warn "Life has no meaning" if not $meaning->is_valid;
The purpose of the rop function is to let you focus in the happy path and provide a nice way to treat failures without filling the code with evals and ifs that always serve almost the same purpose.
rop
eval
if
Supose you have a computation that can fail depending on some condition. For the sake of simplicity consider the following code
sub compute_meaning { my $divisor = shift; return 2 + 80 / $divisor; };
that will fail when called with a zero argument.
Following the style of the Railway Oriented Programming, you wrap the part that could fail in a rop block and focus on programming the happy path:
sub compute_meaning { my $divisor = shift; return rop { 80 / $divisor } ->then(sub { $_ + 2 }); };
This way, the compute_meaning function will never blow, even when passed in a zero argument and the computation doesn't make sense. The caller can check that the computation succeeded by asking the rop result object.
compute_meaning
When the computation succeeds, the value property contains the computation result
value
my $meaning = compute_meaning(2); say "The life meaning is " $meaning->value if $meaning->is_valid;
and when the computation fails, you can also inform the user or decide how to proceed, by inspecting the failure value, which will contain the captured error.
failure
my $meaning = compute_meaning(0); warn "Life has no meaning: " . $meaning->failure if not $meaning->is_valid;
The real usability gain of using rop occurs when you have a recipe that comprises several things to do and you need to stop at the first step that fails.
That is, you need to chain or compose several functions that in the happy path would be executed one after another but in the real path, you would have to check for any of them if had failed or not and proceed with the next or stop and report the errors.
With rop you can leverage the checking to the library and just program the happy path functions and chain them with the then method:
then
use Error::ROP; my $res = rop { 40 / $something } ->then(sub { $_ / 2 }) ->then(sub { $_ * 4 }) ->then(sub { $_ + 2 });
You can always know if the computation has succed by inspecting the rop,
say $res->value if $res->is_valid;
or treat the error otherwise
warn $res->failure if not $res->is_valid;
The computation will short-circuit and return with the first error occurred, no matter how many chained functions remain after the failing step.
This module does not implement the Either type in Perl. The Haskell, F#, ML and other strongly typed functional programming languages have Either types. This is not a generic type like Haskell's Either a b.
Either a b
On those PL you have a strong type system and generic programming facilities that allow you to generalize operations into higher abstractions. In particular, you can operate in elevated (monadic) types as if they where first class values and the languages provide tools (generic functions and operators) that allow you to compose those operations by somehow overloading composition.
When adopting an Either type to implement ROP in those languages, you normally use the >=> operator to overload composition. Actually, you use it to compose functions of the type
>=>
>=> :: (a -> Either b e) -> (b -> Either c e) -> (a -> Either c e)
This library just uses a wrapper object (the Error::ROP instance) that has a method then to somehow compose other operations. This is a much less flexible approach but it works and is easy to understand. The two leaves of the type are accessible via the instance's value and failure getters.
The only confusion might be that it ressembles the then function of a promise or future. This is not exactly the same. Just keep that in mind.
You can find more usage examples in the tests t/Then.t. For examples of how to use inside Moose t/Example.t
t/Then.t
t/Example.t
A Dockerfile is provided in order to run the tests without needing any perl in your system. Just run:
Dockerfile
$ make -f Makefile.docker test
This should construct an image with the necessary dependencies, copy the source into the image and run the tests.
Pau Cervera i Badia
CAPSiDE
The source code is located here: https://github.com/paudirac/Error-ROP
Please report bugs to: https://github.com/paudirac/Error-ROP/issues
Copyright (c) 2017 by CAPSiDE
This code is distributed under the Apache 2 License. The full text of the license can be found in the LICENSE file included with this module.
To install Error::ROP, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Error::ROP
CPAN shell
perl -MCPAN -e shell install Error::ROP
For more information on module installation, please visit the detailed CPAN module installation guide.