5
\$\begingroup\$

I know Perl now has given and when to simulate switch/case statements, but these are still experimental and are not guaranteed to be in future versions. Also there was a Switch module for Perl that existed in older versions, but it used source filtering and was considered not very good either, so it went away.

Because of this, I decided to write my own module to simulate switch/case statements.

package Switch;

# Always use these
use strict;
use warnings;

# Imported modules
use Carp;

# Exporter
use Exporter qw(import);
our @EXPORT = qw(switch case break);

# Variable used to break out of the switch statement
my $BREAK;

sub switch {
    my $switch = shift;
    my @cases  = @_;

    # Check that each case has a function associated with it
    if (scalar @cases % 2) {
        croak "Invalid format in switch statement";
    }

    # Initialize BREAK
    $BREAK = 0;

    # Loop through each case
    while (my ($case, $code) = splice @cases, 0, 2) {

        # Check that $code is a code reference
        if (ref $code ne 'CODE') {
            $case = ref 'ARRAY' ? join ', ', @{$case} : $case;
            croak "case($case) does not have a valid function";
        }

        # Handle the default case
        if ($case eq 'default') { $code->(); next; }

        # Handle all other cases
        for (@{$case}) {
            $code->() if $_ eq $switch;
        }

        # Exit loop if BREAK is true
        last if $BREAK;
    }
}

# Construct an array reference of cases
sub case {
    return \@_;
}

# BREAK from the switch statement
sub break {
    $BREAK = 1;
}

1;

__END__

=head1 NAME

Switch - switch statements for Perl.

=head1 VERSION

$Revision: 1.1 $

=head1 SYNOPSIS

  use Switch;

  # Define a switch variable
  $switch = 3;

  # Implement a simple switch statement
  switch($switch,
      case(1)    => sub { print "\$switch = 1\n";      break; },
  case(2, 3) => sub { print "\$switch = 2 or 3\n";        },
  case(3)    => sub { print "\$switch = 3\n";      break; },
      default    => sub { print "default\n";                  },
  );

=head1 DESCRIPTION

The Switch module is designed to implement C-style switch statements in Perl.  The provided
switch variable will be tested against each case and will execute any/all matching cases until all
cases are tested or a break is encountered.

I have included some simple POD documentation that describes the usage.

To me the syntax looks quite elegant (it was the best I could do without using some sort of source filter myself).

What do you think?

What could be improved?

\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

so it went away

While it is true that the Switch module was removed from the Core Perl distribution, it is still available on CPAN. Consider changing the name of your module to be unique.

What do you think?

I think it looks good. Here are some suggestions.

Namespace

It is best to import only what is needed to avoid namespace pollution. Change:

use Carp;

to:

use Carp qw(croak);

Documentation

It is great that you added POD, especially with a SYNOPSIS section.

In the SYNOPSIS, it would be better to declare the variable with my so that it runs with strict enabled:

my $switch = 3;

Also in the SYNOPSIS, instead of importing by default:

use Switch;

I recommend you explicitly list all the imported functions:

use Switch qw(switch case break);

This makes the code self-documenting. It makes it more obvious that these are functions from the module as opposed to built-in functions.

Comments

There are several useful comments in the code. However, I agree with user @Borodin who left a comment on the question that the following comments should be deleted:

# Always use these
# Imported modules
# Exporter
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.