Invalid value

 | Perl | 6 Comments

Let's say that you need to check the validity of some input value. If it is found in a list of acceptable values then you continue otherwise you need to croak some error message.

For starters let's assume that the list of acceptable values is contained in the following array:

my @list = qw(email name telephone address);

Also don't forget that in order to be able to croak you need to include use Carp; in the file.

Here's the most straight forward way to do it:


sub func
{
    my $value = shift;
    my $found = 0;
    for my $next (@list)
    {
        if ($next eq $value)
        {
            $found++;
            last;
        }
    }
    croak "Invalid value '$value'" unless $found;
    ...
}

Here's another especially clever albeit slightly cryptic way to do it[1]:


sub func
{
    my $value = shift;
    { map { $_ => 1 } @list }->{$value}
        or croak "Invalid value '$value'";
    ...
}

Finally, if you are familiar with the List::MoreUtils module, then here's yet another way to do it:


use List::MoreUtils qw/any/;

sub func
{
    my $value = shift;
    croak "Invalid value '$value'";
        unless any { $value eq  $_ } @list
    ...
}

As you can see there are many correct ways to do it and probably many more.

[1] Perl Medic p. 122

6 Comments

Tried to run the 2nd example above but it did not compile.

Oops I guess this example code from the book only works for older versions of Perl? Ask Peter.

However, I found out that the following does work:


    my $x = { map { $_ => 1 } @list };
    $x->{$value} or croak "Invalid value '$value'";

which is kind of lame because it is exactly the same thing, except less elegant. Oh well.

If you are using Perl 5.10 you can also use the smart match operator:

I usually find hashes to be the natural choice for lookups:

my @list = qw(email name telephone address);
my @lookup{@list} = (1) x @list;

sub func
{
my $value = shift;
croak "Invalid value '$value'" unless $lookup{$value};
...
}

(BTW, with javascript disabled, this page displays an anonymous comment form, but rejects any anonymous comment submissions, saying only "invalid request". You might want to either enable anonymous comments or work up a way to prevent the form from being displayed when javascript is off.)

The problem with enabling anonymous comments is that within minutes I start receiving tons of comments spam.

I'll look into a solution for javascript disabled browsers.

Although I would prefer your last example for clarity , here's another way to do it :)

  1 use List::AllUtils qw/reduce/;
  2 use Test::More 'no_plan';
  3 use Carp;
  4 use feature 'say';
  5 my @list = qw(email name telephone address);
  6
  7 sub func {
  8     my $value = $_[0];
  9     reduce {
 10         $a or ($b eq $value);
 11     } (0,@list)
 12     or croak "Invalid value '$_[0]'";
 13 }
 14
 15 ok( !eval{ func('dog')   } , 'not contained test' );
 16 ok(  eval{ func('email') } , 'contained test'     );
 17 # if I didn't use the eval it wouldn't pass the first test :)

You're right, List::Utils can accomplish alot of stuff for you, but I always seem to overlook it when involved with difficult problems. Never heard of List::UtilsAll though, thanks for the tip.

Leave a comment

Recent Entries

A walk along the Keizersgracht
Too often one is so consumed by a jungle of intertwined thoughts that the beauty of the nearby surroundings ... »
Popularity is fickle
The popularity of a given next generation technology is very fickle, and its success or failure depends on many ... »
Where was Kiffin really buried?
Hi There seems to be some confusion on the current resting place of Kiffin Rockwell, some say that his ... »
Going to Portugal
Normally the week just before I leave for summer vacation, I spend hours on end desperately searching for some ... »
A human language
These days it is not very often that a new and exciting Perl book comes along. That's why I ... »