failures(3pm)

πŸ“¦
version 0.004 Β· 4 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– failures(3pm) β€” the lil' manpage, but make it cute πŸ’–

okay so bestie, welcome to failures, a page from the User Contributed Perl Documentation section of your man pages (3pm, iykyk). Buckle up, we're gonna make exception hierarchies not boring πŸ’…


✨ NAME ✨

failures β€” a minimalist exception hierarchy generator. yes, minimalist. it does one thing and it does it gorgeously πŸŽ€


🌸 VERSION 🌸

version 0.004


πŸ¦‹ SYNOPSIS πŸ¦‹

use failures qw/io::file io::network/;
use Try::Tiny;
use Safe::Isa; # for $_isa

try {
    process_file or
        failure::io::file->throw("oops, something bad happened: $!");
}
catch {
    if   ( $_->$_isa("failure::io::file") ) {
        ...
    }
    elsif( $_->$_isa("failure::io") ) {
        ...
    }
    elsif( $_->$_isa("failure") ) {
        ...
    }
    else {
        ...
    }
}

like. look at that. hierarchies that slap 🌈


πŸ’œ DESCRIPTION πŸ’œ

This module lets you define an exception hierarchy quickly and simply. no drama, no 400 lines of boilerplate, just vibes ✨

Here were my design goals:

  • minimalist interface
  • 80% of features in 20% of lines of code
  • depend only on core modules (nearly achieved)
  • support hierarchical error types
  • identify errors types by name (class) not by parsing strings
  • leave (possibly expensive) trace decisions to the thrower

Currently, failures is implemented in under 70 lines of code. under 70 lines. she's tiny and she ate πŸ”₯

Failure objects are implemented with Class::Tiny to allow easy subclassing (see custom::failures), but Class::Tiny only requires core modules, so other than that exception, the 'core only' goal is achieved. (one tiny little exception to the core-only goal, bestie, we're being honest here πŸ™ˆ)


πŸ‘‘ USAGE πŸ‘‘

πŸŽ€ Defining failure categories

use failures qw/foo::bar foo::baz/;

This will define the following classes in the failure namespace:

  • failure
  • failure::foo
  • failure::foo::bar
  • failure::foo::baz

Subclasses inherit, so failure::foo::bar is-a failure::foo and failure::foo is-a failure. it's giving family tree, it's giving lineage, it's giving inheritance πŸ’–

πŸ“ Attributes

A failure class has three attributes: msg, payload, and trace. Their usage is described below. Accessors exist for all three. three attributes, three accessors, no notes πŸ’…

🧚 Throwing failures

The throw method of a failure class takes a single, optional argument that modifies how failure objects are stringified.

If no argument is given, a default message is generated if the object is stringified:

say failure::foo::bar->throw;
# Caught failure::foo::bar

With a single, non-hash-reference argument, the argument is used for the msg attribute and is appended if the object is stringified.

say failure::foo::bar->throw("Ouch!");
# Caught failure::foo::bar: Ouch!

With a hash reference argument, the msg key provides the string to append to the default error. If you have extra data to attach to the exception, use the payload key:

failure::foo::bar->throw({
    msg     => "Ouch!",
    payload => $extra_data,
});

If an optional trace key is provided, it is appended if the object is stringified. To loosely emulate die and provide a simple filename and line number, use the failure->line_trace class method:

failure::foo::bar->throw({
    msg => "Ouch!",
    trace => failure->line_trace,
});

# Caught failure::foo::bar: Ouch!
#
# Failure caught at <FILENAME> line <NUMBER>

To provide a trace just like the Carp module (including respecting @CARP_NOT) use the croak_trace or confess_trace class methods:

failure::foo::bar->throw({
    msg => "Ouch!",
    trace => failure->croak_trace,
});

# Caught failure::foo::bar: Ouch!
#
# Failure caught at <CALLING-FILENAME> line <NUMBER>

failure::foo::bar->throw({
    msg => "Ouch!",
    trace => failure->confess_trace,
});

# Caught failure::foo::bar: Ouch!
#
# Failure caught at <FILENAME> line <NUMBER>
#   [confess stack trace continues]

You can provide a trace key with any object that overrides stringification, like Devel::StackTrace:

failure::foo::bar->throw({
    msg => "Ouch!",
    trace => Devel::StackTrace->new,
});

# Caught failure::foo::bar: Ouch!
#
# [stringified Devel::StackTrace object]

🫢 Catching failures

Use Try::Tiny, of course. Within a catch block, you know that $_ is defined, but it still might be an unblessed reference or something that is risky to call isa on. If you load Safe::Isa, you get a code reference in $_isa that calls isa only on objects.

So catching looks like this:

use Try::Tiny;
use Safe::Isa;

try { ... }
catch {
    if ( $_->$_isa("failure::foo") ) {
        # handle it
    }
};

If you need to rethrow the exception, just use die:

elsif ( $_->$_isa("failure") ) {
    die $_;
}

🌈 Overriding failure class behavior

See custom::failures. (go read it, it's right there πŸ‘€)


⭐ SEE ALSO ⭐

There are many error/exception systems on CPAN. This one is designed to be minimalist. (she's not like the other exception modules πŸ’…)

If you have more complex or substantial needs, people I know and trust seem to be recommending:

  • Throwable β€” exceptions as a Moo/Moose role
  • Throwable::X β€” Throwable extended with extra goodies

Here are other modules I found that weren't appropriate for my needs or didn't suit my taste:

  • Class::Throwable β€” no hierarchy and always builds a full stack trace
  • Error::Tiny β€” blends Try::Tiny and a trivial exception base class
  • Exception::Base β€” complexity on par with Exception::Class, but highly optimized for speed
  • Exception::Class β€” once highly recommended, but even the author now suggests Throwable
  • Exception::Simple β€” very simple, but always uses caller and has no hierarchy
  • Exception::Tiny β€” not bad, but always uses caller and setting up a hierarchy requires extra work
  • Ouch β€” simple, well-thought out, but no hierarchy; also cutesy function names

Here are some that I'm very dubious about:

  • Err β€” alpha since 2012
  • Error β€” no longer recommended by maintainer
  • errors β€” "still under design" since 2009
  • Exception β€” dates back to 1996 and undocumented
not the "alpha since 2012" πŸ’€ the way some of these have been in limbo longer than some of us have been alive. respect though, we don't do mean here 🫢

πŸŽ€ SUPPORT πŸŽ€

πŸ’– Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker at <https://github.com/dagolden/failures/issues>. You will be notified automatically of any progress on your issue. (bestie you'll literally get pinged, no ghosting here ✨)

πŸ’œ Source Code

This is open source software. The code repository is available for public review and contribution under the terms of the license.

<https://github.com/dagolden/failures>

git clone https://github.com/dagolden/failures.git

🌟 AUTHOR 🌟

David Golden <dagolden@cpan.org>

🌸 CONTRIBUTOR 🌸

Michael Jemmeson <mjemmeson@cpan.org>

This software is Copyright (c) 2013 by David Golden.

This is free software, licensed under:

The Apache License, Version 2.0, January 2004

okay that's the whole page bestie, you're officially a failures expert now πŸ‘‘

this lil' cutie lives on perl v5.36.0, and this version of the page is dated 2022-12-07. go forth and throw your exceptions with main character energy πŸ’…βœ¨

πŸ“¦ where this page comes from