Acme-constant

 view release on metacpan or  search on metacpan

lib/Acme/constant.pm  view on Meta::CPAN

package Acme::constant;
{
  $Acme::constant::VERSION = '0.1.3';
}
use 5.014;
use strictures 1;
use Carp ();

sub generate_constant {
    my ($package, $name, @values) = @_;
    # Prototype is used to make it work like a constant (constants
    # shouldn't take arguments). While anonymous subroutines don't use
    # prototypes, the prototype gets meaning when this subroutine is
    # assigned to type glob.
    my $constant = sub () : lvalue {
        # When constant used as array, it's very simple to understand
        # user wants an array. The !defined wantarray check is intended
        # to detect use of wantarray() in void context.
        if (wantarray || !defined wantarray) {
            @values;
        }
        # When constant has one element, writing to it in scalar
        # context is fine.
        elsif (@values == 1) {
            $values[0];
        }
        # This shows an error, as otherwise, this could cause a strange
        # situation where scalar A shows (A)[0], when A has one
        # element, and 2 when A has two elements. The behavior of Array
        # constructor in ECMAScript is already confusing enough (new
        # Array(3) is [,,,], but new Array(3, 3) is [3, 3]).
        else {
            Carp::croak "Can't call ${package}::$name in scalar context";

            # Return lvalue in order to make older versions of Perl
            # happy, even when it's not going to be used.
            @values;
        }
    };
    # Make a block, to make a scope for strict "refs".
    {
        # Because of symbol table modifications, I have to allow
        # symbolic references.
        no strict qw(refs);
        *{"${package}::$name"} = $constant;
    }
}

sub import {
    my $package = caller;

    # The first argument is this package name
    my $name = shift;

    # Without arguments, simply fail.
    if (@_ == 0) {
        Carp::carp qq[Useless use of "$name" pragma];
    }

    # When called with one argument, this argument would be hash
    # reference.
    elsif (@_ == 1) {
        my %hash = %{shift()};
        # each is safe here, as %hash is lexical variable.
        while (my ($name, $value) = each %hash) {
            generate_constant $package, $name, $value;
        }
    }

    # Otherwise, assume one constant, that possibly could return a list
    # of values.
    else {
        my $name = shift;
        generate_constant $package, $name, @_;



( run in 0.599 second using v1.01-cache-2.11-cpan-98e64b0badf )