使用标量和Perl一样的条件(Using a scalar as a condition in pe

2019-09-21 05:47发布

首先计时器...所以让我知道如果有什么,我还没有重视,同时提出一个问题。

现在的问题是如何用一个标量为条件,如下面的代码无法正常工作。

my @parameter=('hub');

my %condition;
$condition{'hub'}{'1'}='$degree>=5';

foreach (@parameter) {
       if ($condition{$_}{'1'}) {..}
}

我想那是因为条件不正确的解释,所以我也试过以下,这也没有工作。

if ("$condition{$parameter}{'1'}") { ..}

会很感激的任何帮助。 :)

Answer 1:

要么你想要的字符串的eval,后者评估字符串作为Perl代码

if (eval $condition{$_}{'1'}) { ...

或者一个更安全的方法是使用代码引用

$condition{'hub'}{'1'} = sub { return $degree>=5 };

if ($condition{$_}{'1'}->()) { ...

在第二示例中,要连接的一段代码到一个变量。 该$var->()语法执行的代码,并评估该代码的返回值。



Answer 2:

你所要做的就是评估“$度> = 5”作为真正的代码。 而不是试图评价字符串作为密码(这是可以做到的EVAL ),它通常是安全的,往往更稳健,而不是通过代码引用。 您可以使用一台发电机子程序按需生成条件潜艇,就像这样:

sub generate_condition {
    my ( $test, $bound ) = @_;
    return sub { return $test >= $bound; };
}

my %condition;
$condition{'hub'}{'1'} = generate_condition( $degree, 5 );

if( $condition{$parameter}{1}->() ) { ... }

就有点比较麻烦,如果你想>= (即关系本身)进行动态创建。 然后,你有一对夫妇的选择。 一个带你回到拉丝EVAL,其所有的风险(尤其是如果你开始让用户指定的字符串)。 另一个将是你中的查找表generate_condition()子。

generate_condition()返回一个子程序引用,当被调用时,将评价这是在创建时结合在条件。

这里是一个广义的解决方案,将接受任何Perl的条件句,并与参数被测试到一个子程序包沿着他们。 然后,子参考可以被调用,以评估条件:

use strict;
use warnings;
use feature qw/state/;

sub generate_condition {
    my ( $test, $relation, $bound ) = @_;
    die "Bad relationship\n" 
        if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
    state $relationships = {
        '<'     => sub { return $test <   $bound },
        '<='    => sub { return $test <=  $bound },
        '=='    => sub { return $test ==  $bound },
        '>='    => sub { return $test >=  $bound },
        '>'     => sub { return $test >   $bound },
        '<=>'   => sub { return $test <=> $bound },
        'lt'    => sub { return $test lt  $bound },
        'le'    => sub { return $test le  $bound },
        'eq'    => sub { return $test eq  $bound },
        'ge'    => sub { return $test ge  $bound },
        'gt'    => sub { return $test gt  $bound },
        'cmp'   => sub { return $test cmp $bound },
    };
    return $relationships->{$relation};
}


my $true_condition  = generate_condition( 10, '>', 5 );
my $false_condition = generate_condition( 'flower', 'eq', 'stamp' );

print '10 is greater than 5: ', 
      $true_condition->()  ? "true\n" : "false\n";
print '"flower" is equal to "stamp": ', 
      $false_condition->() ? "true\n" : "false\n";

通常,当你构建这些各种各样的事情之一是有意留下开一个参数在呼叫时间,而不是在子程序制造时绑定。 比方说,你只需要绑定的“ $bound ”和“$关系”的参数,但离开“ $test ”开放供子程序调用时间规范。 你会修改你这样的子一代:

sub generate_condition {
    my ( $relation, $bound ) = @_;
    die "Bad relationship\n" 
        if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
    state $relationships = {
        '<'     => sub { return $_[0]  <   $bound },
        # ......

然后调用它像这样:

my $condition = generate_condition( '<', 5 );
if( $condition->(2) ) {
    print "Yes, 2 is less than 5\n";
}

如果目标是提供后期绑定左手和关系评估右手边的都有,这将工作:

sub generate_condition {
    my $relation = shift;
    die "Bad relationship\n" 
        if ! $relation =~ m/^(?:<=?|>=?|==|l[te]|g[te]|cmp)$/;
    state $relationships = {
        '<'     => sub { return $_[0]  <   $_[1] },
        '<='    => sub { return $_[0]  <=  $_[1] },
        # ...... and so on .....
    return $relationship->($relation);
}

my $condition = generate_condition( '<' );
if( $condition->(2,10) ) { print "True.\n"; }

这类工具的落入函数式编程的类别,覆盖着美丽的详细马克·杰森·多明斯的书高阶的Perl



Answer 3:

你有什么期待? 字符串值被解释为true时,他们是空的。

themel@kallisti: ~ $ perl -e 'print "oops\n" if "false" ; '
oops
themel@kallisti: ~ $ perl -e 'print "oops\n" if "" ; '
themel@kallisti: ~ $ perl -e 'print "oops\n" if "\$degree < 5" ;'
oops

如果你想在你的条件来动态评估代码,你必须调查eval 。 例:

my @conds=('$foo>42', '$foo>23');
my $foo = 33;

foreach my $cond(@conds) { 
    print "$cond itself was true\n" if $cond;
    print "$cond evaluated to true\n" if eval($cond);
}

版画

$foo>42 itself was true
$foo>23 itself was true
$foo>23 evaluated to true


文章来源: Using a scalar as a condition in perl