views:

346

answers:

5

In some languages, you can do

$a = $b OR $c OR die("no value");

That is, the OR will short-circuit, only evaluating values from left to right until it finds a true value. But in addition, it returns the actual value that was evaluated, as opposed to just true.

In the above example, in PHP, $a will be the value 1 if either $a or $b are non-false values, or it will die.

So wrote a function first, to be used as

$a = first($a, $b, die("no value"));

which returns the value of either $a or $b. But, it does not short-circuit - it will always die.

Is there a short-circuit OR in PHP that returns the actual value?

Edit: Some good answers for the example I gave, but I guess my example isn't exactly what I meant. Let me clarify.

$a = func1() OR func2() OR func3();

Where each of those functions does a really really intense computation, so I only want to evaluate each expression once at most. And for the first to return a true value, I want the actual value to be stored in $a.

I think we can rule out writing a function, because it won't short-circuit. And the conditional operator answer will evaluate each expression twice.

+8  A: 

No, there isn't, and this is, in my opinion, one of the bad decisions that Zend made in designing PHP that most hobbles competent developers for the sake of coddling incompetent ones.

Edit: In PHP 5.3 and up, you can write $a = $b ?: $c, and even $a = $b ?: $c ?: $d. Still not as good as non-brain-damaged logical operators, but it's something.

chaos
?: syntax is, IMHO, completely unreadable. Short-circuits would have been so much better it's not even comparable :/
Lo'oris
You'll find no argument from me, sir.
chaos
+2  A: 

You could use some kind of coalesce function:

function coalesce() {
    foreach (func_get_args() as $arg) {
        if ($arg) {
            return $arg;
        }
    }
    return null;
}

$a = coalesce($a, $b) or die("no value");
Gumbo
This isn't completely equivalent to a properly working set of logical operators (it doesn't allow complex expressions or function calls to be short-circuited, and of course it has far more overhead), but it's something.
chaos
This is nice, but will evaluate each of the arguments to coalesce, unlike a true short-circuit OR. For example, coalesce(true, launch_missiles()) or die("the end is near") will still result in missiles being launched.
Shawn
A: 

What about variable functions?

function coalesce($funcs)
{
    foreach ($funcs as $func)
    {
        //Catch language constructs
        switch($func)
        {
            case 'die':
                die();
        }
        $result = $func();
        if ($result)
        {
            return $result;
        }
    }
}
Nate Wagar
+3  A: 

You can use just:

$a = func1() or $a = func2() or $a = func3();

or am I missing something?

ntd
Not exactly what I was looking for, but it's clean and it works. Thanks.
Steve
For sufficiently filthy values of "clean".
chaos
A: 

This should work:

$a = (($f1=func1()) ? $f1 : ($f2=func2()) ?  $f2 : func3()) );
ChronoFish