Perl是否有类似于PHP的常量()的东西?

时间:2009-10-06 17:04:54

标签: php perl variables constants

我已经完成了对perldoc和O'Reilly书籍的一些挖掘,但还没有找到任何方法来做到这一点。我是不是喜欢使用像Readonly这样的东西?

更新

我对Readonly没有任何反对意见。我只是想做一些像PHP的常量()。

示例,如果Perl有constant():

use constant {
  FIELD_EXAMPLE_O => 345,
  FIELD_EXAMPLE_L => 25
};

my $var = 'EXAMPLE';
my $c = 'FIELD_' . $var . '_L';
my $value = constant($c);

# $value is 25

如果Readonly是最好的方法,那么我将使用它。

7 个答案:

答案 0 :(得分:15)

Readonly出了什么问题?

如果速度太慢,可以使用Readonly:XS补充它。但如果你不喜欢Readonly,那么总是会有较旧的constant

use constant PI => 3.14159265;

记住

  1. 他们像子一样工作,因此他们不会在没有工作的情况下进行插值。
  2. 如果要在一个语句中创建多个常量,则需要传递哈希引用。

    use constant { PI => 3.14159265
                 , E  => 2.71828183
                 };
    

  3. 来自您的示例:

    从您的示例来看,没有理由认为只读哈希不能做同样的事情。

    Readonly::Hash my %field_example => { L => 25, O => 345 };
    

    然后你可以在任何你想要拼凑常数的地方使用它:

    print "The example is $field_example{$var}\n";
    

    或者你可以这样做:

    Readonly::Hash my %field 
        => { example => { L => 25,     O => 345 }
           , name    => { L => 'Lion', O => 'ocelot' }
           };
    

    并以这种方式称呼它:

    $field{$var}{L};
    

    你可以获得很多里程碑,不要试图让语言做得更好,支持用另一种方式做。

    同意PHP constant

    但是,如果你想这样做,那么我的建议是以下子是一种做同样的方法(并避免使用eval):

    sub read_constant { 
        use Symbol qw<qualify_to_ref>;
        my $name = join( '', @_ ); # no need to concatenate before passing
        my $constant;
        # use the first that works: calling package and then "" (main)
        for my $pkg ( scalar( caller ), "" ) { 
            # get symbol reference
            my $symb_ref = qualify_to_ref( $name, $pkg );
            # get the code slot
            $constant    = *{$symb_ref}{CODE};
            last if $constant;
        }
        return unless $constant;
        # call the sub named
        return $constant->();
    }
    

    你会这样称呼它:

    $value = read_constant( 'FIELD_', $var, 'L' );
    

    最后一件事是,您甚至可以在前面进行测试,以确保它只是一个全部上限字符串:

    Carp::croak "Invalid constant name '$name'" if $name =~ /[^\p{UpperCase}_]/;
    

答案 1 :(得分:10)

您可以使用constant

use constant PI    => 4 * atan2(1, 1);
use constant DEBUG => 0;

print "Pi equals ", PI, "...\n" if DEBUG;

use constant {
    SEC   => 0,
    MIN   => 1,
    HOUR  => 2,
    MDAY  => 3,
    MON   => 4,
    YEAR  => 5,
    WDAY  => 6,
    YDAY  => 7,
    ISDST => 8,
};

use constant WEEKDAYS => qw(
    Sunday Monday Tuesday Wednesday Thursday Friday Saturday
);

print "Today is ", (WEEKDAYS)[ (localtime)[WDAY] ], ".\n";

或者您可以使用Readonly

use Readonly;

# Read-only scalar
Readonly::Scalar     $sca => $initial_value;
Readonly::Scalar  my $sca => $initial_value;

# Read-only array
Readonly::Array      @arr => @values;
Readonly::Array   my @arr => @values;

# Read-only hash
Readonly::Hash       %has => (key => value, key => value, ...);
Readonly::Hash    my %has => (key => value, key => value, ...);
# or:
Readonly::Hash       %has => {key => value, key => value, ...};

# You can use the read-only variables like any regular variables:
print $sca;
$something = $sca + $arr[2];
next if $has{$some_key};

# But if you try to modify a value, your program will die:
$sca = 7;
push @arr, 'seven';
delete $has{key};
# The error message is "Modification of a read-only value attempted"

答案 2 :(得分:7)

是。请参阅perldoc constant

答案 3 :(得分:4)

以下是您正在寻找的constant功能:

sub constant
{
  no strict 'refs';
  shift->();                    # Call the supplied function by name
} # end constant

只需将其添加到问题中的代码中,它就会按照您的要求执行操作。 constant pragma创建的常量只是子程序,并且可以很容易地按名称调用子程序。

这是一个更高级的,即使你从另一个包调用它仍然有效:

sub constant
{
  my $constant = shift;
  $constant = caller() . "::$constant" unless $constant =~ /::/;
  no strict 'refs';
  $constant->();                # Call function by name
} # end constant

答案 4 :(得分:1)

您可以使用“use constant”编译指示,但是以这种方式定义的常量不像普通变量那样被引用。但它们确实可以让你获得常量的性能提升。如果您不是在寻找使用常量的编译时优化,那么您最好的方法可能只是在编写代码时使用规则而不是分配给不应该分配的变量。 :)

答案 5 :(得分:1)

查看您发布的示例代码,我感觉您可能正在寻找Hash::Util::lock_hash和朋友:

#!/usr/bin/perl

use strict;
use warnings;

use Hash::Util qw(lock_hash);

my %constant = (
    FIELD_EXAMPLE_O => 345,
    FIELD_EXAMPLE_L => 25,
);

lock_hash %constant;

my $var = 'EXAMPLE';

print $constant{"FIELD_${var}_L"}, "\n";

输出:

C:\Temp> xuk
25

答案 6 :(得分:0)

使用以下格式:

use constant DFLT_MIN_LENGTH_PWD => 6;