21

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.

chaos
  • 122,029
  • 33
  • 303
  • 309
Steve
  • 4,033
  • 5
  • 32
  • 29
  • 2
    This will, of course, always die. When you call a function, PHP must first evaluate all the parameters. During the evaluation, it sees 'die("no value")' and does just that. – Tom Oct 08 '09 at 17:16
  • 1
    Evaluating each expression twice was fine when we were talking about variables. You have to spell out your question the first time around, and not criticize an answer after presenting additional information which was not available the first time. If you meant functions, use functions the first time. The best answer is now chaos's "No." – Jed Smith Oct 08 '09 at 17:54
  • 1
    comment #2 is wrong. php has short-circuit evaluation but AFAIK does not return the left-most vale. It always returns a boolean. – apinstein Jan 02 '12 at 14:04

6 Answers6

29

No, there isn't, and this is, in my opinion, one of the bad decisions that Rasmus Lerdorf 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
  • 122,029
  • 33
  • 303
  • 309
9

You can use just:

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

or am I missing something?

ntd
  • 7,372
  • 1
  • 27
  • 44
  • Not exactly what I was looking for, but it's clean and it works. Thanks. – Steve Oct 08 '09 at 18:24
  • 17
    For sufficiently filthy values of "clean". – chaos Oct 08 '09 at 19:06
  • 3
    I will upvote the answer but it would be nice if I could downvote the language – Steven Lu May 05 '15 at 00:41
  • @StevenLu, `am I missing something` is used to clarify whether the person was _misunderstanding_ the query and is actually giving an irrelevant answer. Given that @ntd's idea was so mechanically simple, it's reasonable and appropriate for him to assume/expect that there's a decent chance that wasn't what @Steve was looking for—that he could be _missing something_ about Steve's query. While this phrase (as with most words) _can_ be used sarcastically, it seems a good-faith effort here by ntd to open the discussion in the (highly likely) event that his answer was missing a core fact of the OP. – JamesTheAwesomeDude Jul 20 '20 at 15:26
  • @JamesTheAwesomeDude Yeah I'm kinda missing the context here 5 years later. Doesn't look like the answer was edited, and I have enough rep to edit stuff now too :) But yeah I don't see anything that's a problem here. I also don't know why my comment got 3 upvotes. ‍♂️ – Steven Lu Jul 20 '20 at 17:56
  • Oh. @JamesTheAwesomeDude I think I was making a snide comment about how terrible of a language PHP is. Not that the answerer used poor language! Sorry for the misunderstanding and the poor attitude. – Steven Lu Jul 20 '20 at 17:57
  • @StevenLu I think one of the upvotes in your comment was mine. I don't like PHP either and I always implied "programming" language in this context. I did not even think this could be misunderstood... until now. – ntd Oct 20 '20 at 08:26
2

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
  • 643,351
  • 109
  • 780
  • 844
  • 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 Oct 08 '09 at 17:24
  • 1
    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 Oct 08 '09 at 17:28
1

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
  • 640
  • 2
  • 7
  • 18
1

I'm sorry, but most of these answer are just off.

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

becomes

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

The reason OR doesn't work is that instead instead of returning the former or latter value it returns true or false.

Anfurny
  • 134
  • 13
0

This should work:

$a = (($f1=func1()) ? $f1 : ($f2=func2()) ?  $f2 : func3()) );
ChronoFish
  • 3,589
  • 5
  • 27
  • 38