【问题标题】:How can I have PHP avoid lazy evaluation?如何让 PHP 避免延迟评估?
【发布时间】:2009-04-02 18:09:50
【问题描述】:

关于 PHP 计算布尔表达式的方式,我有一个有趣的问题。例如,当你有,

$expression = $expression1 and $expression2;

或

if ($expression1 and $expression2)

PHP 首先检查 $expression1 的计算结果是否为 true。如果不是这种情况,则简单地跳过$expression2 以避免不必要的计算。在我正在编写的脚本中,我有:

if ($validator->valid("title") and $validator->valid("text"))

即使第一个语句的计算结果为假,我也需要评估第二个语句 ($validator->valid("text"))。我想问你是否有一些简单的方法可以强制 PHP 总是评估这两个语句。谢谢!

【问题讨论】:

    标签: php function lazy-evaluation boolean-logic


    【解决方案1】:
    $isValidTitle = $validator->valid("title");
    $isValidText = $validator->valid("text");
    if($isValidTitle && $isValidText)
    {
        ...
    }
    

    这样合适吗?

    【讨论】:

    • 我喜欢这个解决方案,因为它明确指出方法应该作为代码执行,而不是简单的测试。有一些学派认为,具有副作用的语句不应该进入控制语句——控制语句仅用于测试,从不执行。
    【解决方案2】:

    这称为short circuit evaluation,为避免这种情况,您需要使用单个&:

    if($validator->valid("title") & $validator->valid("text")) {
    
    }
    

    请注意,这里使用的不是logical operators,而是bitwise operators:

    它们是作用于数字的二进制表示的运算符。它们不会将逻辑值(即“true”或“false”)作为参数,而无需先将它们分别转换为数字 1 和 0。它们也不返回逻辑值,而是返回数字。当然,您可以稍后将这些数字视为逻辑值(在这种情况下,0 被强制转换为“false”,其他任何内容都被强制转换为“true”),但这是 PHP 类型转换规则的结果,无需执行任何操作与操作员的行为有关。

    因此,对于使用这种副作用来规避短路评估是否是良好做法存在一些争论。我个人至少会发表评论说 & 是故意的,但如果你想尽可能纯粹,你应该先评估它们是否有效,然后再做 if。

    【讨论】:

    • 这是非常不明智的。如果第一个返回 true,而后者返回 2. true&2 make false 怎么办!此外,维护者可能会走过来说“哎呀,应该是 &&,而不是 &”,从而破坏了代码。 stackoverflow.com/questions/710919/… 是一个更安全、更清晰的答案。
    • 我很清楚这些限制,你有没有看我的回答?
    • @Paolo Bergantino:我做到了。我想指出,这不应该被选为正确答案,尽管它很聪明(嗯,它真的太聪明了)。
    • 就我个人而言,我认为这是非常聪明,我认为那里有很多 PHP 用户会说“如果第二个参数是一个未实例化的对象怎么办”我投了赞成票因为在澳大利亚,在任何“因为你知道它是做什么的,而不是它是如何做的”的代码 sn-p 中使用 '&' 和 '^' 实际上是非法的,即按位运算符不是 f0re n00bs跨度>
    • 大声笑......我来寻找 PHP 是懒惰的确认,我离开了开始一个优雅的讨论 - 我
    【解决方案3】:

    尝试分别评估每个术语:

    $term1 = $validator->valid("title");
    $term2 = $validator->valid("text");
    if($term1 && $term2) {
    //things to do
    }
    

    【讨论】:

      【解决方案4】:

      这可能不是最好的实现,但您总是可以这样做:

      $a=$validator->valid("title");
      $b=$validator->valid("text");
      if($a && $b) {...}
      

      【讨论】:

        【解决方案5】:

        您可以定义如下函数:

        function logical_and($x,$y) {return ($x && $y);}
        

        由于 PHP 使用按值调用,所以这是可行的。

        【讨论】:

          【解决方案6】:

          或者,如果您可以修改类 $validator 实例化,您可以使有效方法接受字符串或数组。如果它是一个数组,它会运行每个项目上已经存在的代码,并且仅当所有项目都“有效”时才返回 TRUE。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-17
            • 2014-12-24
            • 2010-10-03
            • 1970-01-01
            • 2012-02-03
            • 1970-01-01
            • 2021-12-18
            相关资源
            最近更新 更多