【问题标题】:Does Perl have something similar to PHP's constant()?Perl 是否有类似于 PHP 的常量()的东西?
【发布时间】:2010-12-04 08:29:49
【问题描述】:

我已经通过 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 是最好的方法,那么我将使用它。

【问题讨论】:

  • Readonly 非常好。你能解释一下你认为它有什么问题吗?

标签: php perl variables constants


【解决方案1】:

Readonly 有什么问题?

如果太慢,可以补充Readonly:XS。但如果你不喜欢Readonly,总会有旧的constant

use constant PI => 3.14159265;

记住

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

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

从你的例子:

从你的例子来看,没有理由只读 hash 不能做同样的事情。

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

但是,如果您想这样做,那么我的建议是以下 sub 也是这样做的一种方式(并避免使用 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}_]/;

【讨论】:

【解决方案2】:

你可以使用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"

【讨论】:

    【解决方案3】:

    是的。见perldoc constant

    【讨论】:

      【解决方案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
      

      【讨论】:

      • +1 我想我们都没有真正理解 OP 的目的。
      • 太棒了!您已经找到了禁用 use strict 的少数充分理由之一。更好的是,您可以在有限的词法范围内执行此操作。
      【解决方案5】:

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

      【讨论】:

      • Perl 中的许多问题似乎都可以通过“不要那样做!”来解决。为我工作。
      【解决方案6】:

      查看您发布的示例代码,我感觉您可能正在寻找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

      【讨论】:

        【解决方案7】:

        使用这种格式:

        use constant DFLT_MIN_LENGTH_PWD => 6;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-15
          • 1970-01-01
          • 1970-01-01
          • 2011-12-04
          • 2011-01-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多