为什么是 ”!!”在Perl中被认为是不好的形式?

时间:2015-10-08 11:09:49

标签: perl boolean type-conversion

在最近的求职面试过程中,我提交了一些使用所谓“秘密”!! operator的Perl代码示例。后来,在讨论代码时,其中一位采访者问我为什么选择使用它,并表示它被认为是不好的形式。他没有详细说明原因。

我和我的团队多年来一直在使用这个操作员,却没有意识到它被认为是“糟糕的形式”。

“bang bang”操作员是否有副作用或其他意外行为?为什么它或者可能被某些人认为是“糟糕的形式”?是否有惯用的替代方案?

下面是一些我认为!!可接受和/或可取的例子。

  1. 编码练习中的实际代码,这是添加布尔值的一个例子:

    while (my $line = <$F>) {
        # snip
        exists $counts{lines} and $counts{lines} += !! chomp $line;
    }
    
  2. 使用布尔值作为哈希键(显然是简化示例):

    sub foo {
        my ($input) = @_;
        my %responses = ( '' => "False", 1 => "True" );
        return $responses{ !! $input };
    }
    
  3. 在按位运算中使用布尔值,甚至是pack()

    sub foo {
        my ( $a, $b, $c ) = @_;
        my $result = !!$a + (!! $b)<<1 + (!! $c)<<2;
        return $result;
    }
    
  4. 您需要进行类型转换以供外部库/进程使用,例如数据库,它只考虑某些值是真实的:

    my $sth = $dbh->prepare("INSERT INTO table (flag,value) VALUES (?,?)")
    $sth->execute("i_haz_cheeseburger", !! $cheeseburger_string)
    

5 个答案:

答案 0 :(得分:65)

我称之为“糟糕的形式”,因为它根本就没有必要。你不需要在Perl中进行布尔转换。所以充其量是多余的,最糟糕的是它是一种混淆。

虽然你可以在Perl中使用一些非常好的技巧,但语言最大的问题之一(至少在感知上)是它很容易“编写一次”代码。

毕竟 - 当你可以测试标量时,为什么你需要'双否定'一个标量来得到一个布尔值?

my $state = !! 'some_string';
if ( $state ) { print "It was true\n" };

或者:

if ( 'some_string' ) { print "It was true\n" };

这是真的 - 由于“秘密”操作符,基于标点符号的变量等,你可以编写一些可怕的无法理解的Perl代码。它会工作得很好 - 例如 - 我仍然认为这是一个杰作:{{3} }

但它不是'好代码'。对于“真实世界”的使用,您的代码需要清晰,易懂且易于排除故障。

关于替代方案;

while (my $line = <$F>) {
    # snip
    exists $counts{lines} and $counts{lines} += !! chomp $line;
}

这是......计算你认为我成功chomp行的频率?所以基本上它只计算输入中的行数。

为此,我会考虑“使用$.”。除非我错过了你的代码的深刻内容?

  

“如果它没有叮咬怎么办?”

好吧,好吧。怎么样:

 $counts{lines}++ if foo();

为此:

sub foo {
    my ($input) = @_;
    my %responses = ( "" => "False", 1 => "True" );
    return $responses{ !! $input };
}

我会把它写成:

sub foo {
    my ($input) = @_;
    return $input ? "True" : "False";
}

对于最后一个条件 - 将标志打包成一个字节:

sub flags {
    my @boolean_flags = @_;
    my $flags = 0;
    for ( @boolean_flags ) {
        $flags<<=1;
        $flags++ if $_;
    }
    return $flags;
}

print flags ( 1, 1, 1 );

或许如果你正在做类似的事情 - 通过定义基于位置添加的值来从3-D Stereogram, Self replicating source如何做到这一点,所以你不必担心位置参数问题:

  

您可以使用标记:flock请求提供flock()常量(LOCK_SH,LOCK_EX,LOCK_NB和LOCK_UN)。

然后你可以:

flock ( $fh, LOCK_EX | LOCK_NB );

它们是按位定义的,因此它们通过or运算符“添加” - 但这意味着它是幂等操作,其中设置LOCK_NB两次不会。

例如,

 LOCK_UN = 8
 LOCK_NB = 4
 LOCK_EX = 2
 LOCK_SH = 1

如果我们将问题扩展到不那么主观的话:

  

我要求避免的理由!!

  • Perl评估变量的“真实性”,因此实际上并不需要实际的逻辑布尔值。
  • 条件语句比它们的等效布尔代数更清晰。 if ( $somecondition ) { $result++ }$result += !! $somecondition更清晰。
  • 它位于一个秘密的运营商列表,因为它是模糊的。您未来的维护程序员可能不会那么欣赏。
  • !!11!!0dualvar('', 0)。虽然这很灵活,但它会让人感到惊讶,特别是因为大多数人甚至不知道双变量是什么,更不用说!返回一个变量。如果您使用三元组,则明确表示您获得的值:$value ? 1 : 0

答案 1 :(得分:38)

你的!!利用了Perl中两个不起眼的东西:!返回的具体值,其中一个可能的值是dualvar(包含字符串和数字的标量)。使用!!来复合这些行为无疑是精辟的。虽然它的简洁性可以是一个巨大的优势,它也可以是一个相当大的减号。不要使用导致项目强制要求的功能,禁止在此项目中使用Perl。&#34;

$count += !! (some_expression)有很多替代方法可以计算该表达式的真实值的出现次数。一个是三元组$count += (some_expression) ? 1 : 0。这也有点模糊。有一个很好的紧凑方式来做你想要的,即使用post-if:

$x++ if some_expression;

这正是你正在做的事情。

答案 2 :(得分:19)

整个问题有点主观,所以我想提出一个与迄今为止发布的其他答案不同的意见。我不会考虑一般的双重否定形式,但如果有更可读的替代方案,我会尽量避免它。关于你的例子:

  1. 使用$count++ if $condition

  2. 之类的内容
  3. 真值是否为哈希键?那简直就是邪恶。至少,对于需要维护代码的人来说,这是令人惊讶的。

  4. 此处使用!!是合理的。

  5. 这里我使用三元运算符。传递双变量时,execute的行为并不是很清楚。

  6. 使用!!完全正常的另一种情况是将某些值转换为布尔值,例如在return语句中。类似的东西:

    # Returns true or false.
    sub has_item {
        my $self = shift;
        return !!$self->{blessed_ref};
    }
    

    大多数程序员应该从静态类型语言中了解!!成语,它通常用作强制转换为强制转换。如果这就是你想要做的事情并且没有不必要的副作用的危险,那就去做双重否定。

答案 3 :(得分:7)

也许只有你看到的代码并没有那么糟糕。

但是,您的开发人员可能会在有一天看到它修复代码中的错误,并偶然发现错误。有两个选项

  1. 他认为你犯了一个错误并删除了一个!,使你的代码无效
  2. 他认为这只是软件腐烂,并且毫不犹豫地删除了!!。在重构其他一些代码后,它突然挂起......类型不匹配?
  3. 无论哪种方式,它都会浪费未来开发人员的时间,除非他们碰巧熟悉它。可理解的代码永远不会为您自己(好吧,它可能有所帮助),但对于任何其他人都会看到您的代码。

答案 4 :(得分:3)

根据工作的不同,很多商业和面试的原因也很糟糕......

  1. 在处理团队项目时,或许多其他开发人员可能正在处理的任何其他代码时,不要混淆(或遵循公司政策)
  2. 对于sanchises所说的,它将导致更多的工作,并且没有清楚地显示代码的意图。
  3. 它根本就没有必要,如上所述 - 听起来至少有一种情况,结果不起作用 - 因此是一个错误。
  4. 在面试中展示了模糊编码的用法,当有一种更容易和更清晰的方式时,在面试中看起来并不好看。
  5. 面试是指你想表明自己是团队合作者的地方,而不是你要扼杀任何其他人都不理解的奇怪废话(当然,除非碰巧是未解决问题的答案)< / LI>

    P.S。要问面试官他为什么认为这是“不良形式”,这样做会很好。一个方便的采访后续提示,就是向他发送一个感谢信,并问他为什么会这么认为&#34;糟糕的形式&#34;