Errors in Perl

In Perl, error handling is typically done using return values and the die function for fatal errors. We’ll use this approach to mimic Go’s error handling.

use strict;
use warnings;

# By convention, errors are typically indicated by returning
# undef or a false value, with the error message in $@.

sub f {
    my ($arg) = @_;
    if ($arg == 42) {
        # In Perl, we can set $@ to indicate an error
        $@ = "can't work with 42";
        return undef;
    }
    # A defined return value indicates no error
    return $arg + 3;
}

# In Perl, we can use constants for sentinel errors
use constant ERR_OUT_OF_TEA => "no more tea available";
use constant ERR_POWER => "can't boil water";

sub make_tea {
    my ($arg) = @_;
    if ($arg == 2) {
        return ERR_OUT_OF_TEA;
    } elsif ($arg == 4) {
        # In Perl, we can concatenate strings to add context
        return "making tea: " . ERR_POWER;
    }
    return undef;
}

sub main {
    foreach my $i (7, 42) {
        # It's common to use an inline error check
        my $r = f($i);
        if (!defined $r) {
            print "f failed: $@\n";
        } else {
            print "f worked: $r\n";
        }
    }

    for my $i (0..4) {
        my $err = make_tea($i);
        if (defined $err) {
            # In Perl, we can use string comparison for error checking
            if ($err eq ERR_OUT_OF_TEA) {
                print "We should buy new tea!\n";
            } elsif ($err =~ /^making tea: /) {
                print "Now it is dark.\n";
            } else {
                print "unknown error: $err\n";
            }
            next;
        }
        print "Tea is ready!\n";
    }
}

main();

This Perl code mimics the error handling approach of the original Go code. Here are some key points:

  1. In Perl, we typically use undef or false return values to indicate errors, often setting $@ with the error message.

  2. We use constants (use constant) to define sentinel errors, similar to Go’s predefined error variables.

  3. Error checking is done by checking if the return value is defined (defined) or true.

  4. String concatenation is used to wrap errors, similar to Go’s fmt.Errorf.

  5. For error type checking, we use string comparison (eq) or regular expressions (=~), as Perl doesn’t have a built-in error type system like Go.

To run this program, save it as errors.pl and use:

$ perl errors.pl
f worked: 10
f failed: can't work with 42
Tea is ready!
Tea is ready!
We should buy new tea!
Tea is ready!
Now it is dark.

This example demonstrates how to handle and check for specific errors in Perl, providing a similar structure to the Go example while using Perl-specific idioms and constructs.