代码之家  ›  专栏  ›  技术社区  ›  Chris Kloberdanz

Perl是否有类似于PHP常量()的内容?

  •  5
  • Chris Kloberdanz  · 技术社区  · 16 年前

    我已经在perldoc和O'Reilly的书中做了一些挖掘,但还没有找到任何方法。我是否被降级到使用类似的东西 Readonly ?

    更新:

    我不反对Readonly。我只是想做一些类似PHP的常量()的事情。

    如果Perl具有常量(),则示例如下:

    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 回复  |  直到 16 年前
        1
  •  15
  •   Axeman maxelost    16 年前

    你怎么了 Readonly

    如果它太慢,你可以补充它 Readonly:XS . 但是如果你不喜欢 只读 ,总是有老的 constant

    use constant PI => 3.14159265;
    

    记住

    1. 它们像潜艇一样工作,因此不需要做功就不会插值。
    2. 如果要在一条语句中创建多个常量,则需要传递哈希引用。

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

    从你的例子来看:

    从您的示例判断,没有理由使用只读 搞砸 不能做同样的事情。

    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同源 常数

    但是,如果您想这样做,那么我的建议是,下面的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
  •  10
  •   Brad Gilbert    16 年前

    你可以用 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
  •  7
  •   Brad Gilbert    16 年前

    对看见 perldoc constant .

        4
  •  4
  •   cjm    16 年前

    这是我的建议 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
    
        5
  •  1
  •   dannysauer    16 年前

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

        6
  •  1
  •   Sinan Ünür    16 年前

    通过查看您发布的示例代码,我感觉您可能正在寻找 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
  •  0
  •   Sinan Ünür    16 年前

    使用以下格式:

    use constant DFLT_MIN_LENGTH_PWD => 6;