3
my $target_type = (defined($item->{target_type}) && $item->{target_type}) 
                ? $item->{target_type} 
                : "";

my $target_id   = (defined($item->{target_id}) && $item->{target_id})
                ? $item->{target_id} 
                : "";

为什么开发人员&&在几乎相同的条件下使用?

4

6 回答 6

6

显然他是腰带和吊带式的。 (defined($x) && $x)几乎等同于 just $x,因为undef是假的。(不同之处在于 if $xis undefthen(defined($x) && $x)将是 Perl 的特殊 false 值,该值已定义,但在这种情况下没有区别。)可能曾经有不同的条件(如$x > 0)并且defined测试是必要的以避免警告一个未初始化的值。然后有人删除了那个条件并且没有考虑删除 now-unnecessary defined

使用的另一个原因(defined($x) && $x)(正如onon15 指出的那样$x)是为了向未来可能未定义的维护程序员强调。就个人而言,我会为此使用评论,但TIMTOWTDI

于 2012-09-14T06:30:55.313 回答
2

尽管 && 的右侧可以单独使用,但我已经多次看到这种用法作为人类读者的语义提示,这$item->{target_type}可能没有定义。

因此,即使可以删除 LHS 并保持类似的行为,维护者也可能很容易误认为不需要检查值是否已定义。(除非在一个紧密的循环中,额外评估的成本可以忽略不计,即使在一个循环内,它也可能通过解释器中的优化来消除)。

于 2012-09-14T06:37:52.680 回答
2

非常简短的回答:这是为了避免在旧的 perls 中出现“使用未初始化的值”警告,并在这种情况下分配一个默认定义的值。在 v5.10 及更高版本中,您将使用定义或运算符:

 $scalar //= "";
于 2012-09-14T14:09:03.303 回答
1

&&是一个“逻辑短路”运算符。首先,他正在测试$item->{targ_type}. 当且仅当它被定义(即左侧&&为真)时,他测试是否$item->{target_type}包含真值。如果这两个条件都为真,那么$target_type(以及以后$target_id)被分配保存在$item->{target_type}or中的值$item->{target_id}。如果这些条件之一为假,则分配一个空字符串。

更新:试图读懂提出这个结构的程序员的想法:也许代码的进化方式导致了这种情况,而程序员没有考虑足够长的时间来认识到它是不必要的。也许程序员对 Perl 中定义性、真实性、虚假性以及哪些类型的值是“虚假”之间的区别不安全。

于 2012-09-14T06:29:38.900 回答
1

回答你的问题需要读心术,但这里有一些按概率排序的原因:

  1. 作者不是 Perl 程序员,因此对 的真实性、计算结果并使得表达式的其余部分没有实际意义undef的事实感到不舒服,或者两者兼而有之。defined undef && undef""
  2. 该代码已经看到一个修订版,该修订版删除了需要defined测试才能正常工作的内容,例如defined $x && $x ne ''. 该defined测试是从该编辑中遗留下来的,对维护者具有负面价值。
  3. 作者希望强调该元素可能已经undef过明确测试。有更好的方法可以做到这一点,不会让未来的读者猜测其意图可能是什么。比如说,评论。
  4. 如果已定义,$item->{target_type}则可能包含一个具有重载布尔转换的对象,该对象的计算成本很高,并且您正在寻找一种自我挫败的微优化。这种情况极不可能。不过好笑。
于 2012-09-14T07:42:56.770 回答
0

这不是同一个条件。

首先,他测试定义性

defined($item->{target_type})

当使用未定义的值进行操作时,某些操作毫无意义。

在第二个条件下,他测试一个真值或假值

$item->{target_type}

但是,作为undef一个错误值,第二个测试涵盖了这两种情况。

在某些情况下,类似的模式是必要的,例如在针对参考内容进行测试时。

my $ref1 = "true";
my $ref2 = \("true");

if (ref $ref1 eq 'SCALAR' and $$ref1) {
  # This does not get executed
}
if (ref $ref2 eq 'SCALAR' and $$ref2) {
  # This does get executed
}
于 2012-09-14T06:30:32.613 回答