http://www.perlmonks.org?node_id=1039912

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

In larger programs, I like to guard against typos in hash keys (when the keys are a known, fixed set) using Hash::Util's lock_keys, or I'll retrofit a large program with this module for the same purpose.

Is there something like this for scalars? I.e. something that lets me restrict the value of a scalar to a set of allowed values? (I've searched, but not found anything yet.) Something like this:

tie my $state, 'Scalar::Restrict', qw/ idle waiting active /; # or maybe lock_scalar my $state, qw/ idle waiting active /; # $state may now only be "idle", "waiting", or "active"

Thanks in advance for your thoughts.

Replies are listed 'Best First'.
Re: Restricting a scalar to certain values
by tobyink (Canon) on Jun 20, 2013 at 08:56 UTC

    Type::Tie can be used to tie a scalar, array or hash variable to a type constraint. It supports Type::Tiny, Moose::Meta::TypeConstraint and MooseX::Types type constraints (and probably Mouse::Meta::TypeConstraint and MouseX::Types, though these are untested).

    #!/usr/bin/env perl use strict; use warnings; use Type::Utils qw(enum); use Type::Tie; my $scalar; ttie $scalar, enum ["foo", "bar"]; $scalar = "foo"; # ok $scalar = "bar"; # ok $scalar = "baz"; # dies

    Update: note though that tied scalars are significantly slower than untied. So an idea might be to tie your scalars in your development environment, and keep them untied in production. This can be achieved using something like:

    use constant DEBUG => !!$ENV{DEVELOPMENT_SERVER}; my $scalar; ttie $scalar, enum ["foo", "bar"] if DEBUG;
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Restricting a scalar to certain values
by jakeease (Friar) on Jun 20, 2013 at 08:14 UTC
Re: Restricting a scalar to certain values
by Anonymous Monk on Jun 20, 2013 at 08:31 UTC
Re: Restricting a scalar to certain values
by Anonymous Monk on Jun 20, 2013 at 08:56 UTC

    Thanks jakeease and Anonymous for the feedback so far! I just thought I'd clarify: Yes, it's a bit like an enum - the thing is though that I'd like to retrofit some older scripts that already use a scalar as an enum. It'd be an advantage if I could just add a line at the top saying "restrict this scalar to this set of allowed values" to protect against future typos instead of updating every place where the scalar is used.

Re: Restricting a scalar to certain values
by sundialsvc4 (Abbot) on Jun 21, 2013 at 12:55 UTC

    The only vague approximation that I have seen is use constant {};.   And it is a very poor substitute.   The Perl language simply does not have real enumerated-types or compile-time checking.