短絡評価

まず、プログラミング自体の概念として「短絡評価」というものがあります。
少し例を出してみましょう。

まず、単純な評価として、例えばこんなものがあります。

true && true
true || true
false || true

これは、いわゆる論理演算子( https://www.php.net/manual/ja/language.operators.logical.php )ですね。

んで。これらは、例えば「比較演算子の結果」であったり「関数の戻り値」であったりすることもあります。

($a !== $b) && hoge()

さて。
例えば上述で、$aと$bに「同じ値が入っている場合」と仮定をしてみましょう。
そうすると、こう置き換えられます。

false && hoge()

質問です。上述で、hoge()はcallされるのでしょうか?

「プログラミング言語全般」で考える場合、hoge()がcallされるかは「言語仕様依存、かつ、言語によっては実装依存」になります……ので、こういった書き方を「厳重に戒める」言語も存在します。

一方で「PHP」の場合はどうか? というと、これは言語仕様として決まっていて「callされない」になります。
PHPは、短絡評価を「行う」と明示されている言語だから、です。

ちょっとお堅い文章を引用しつつ、説明をしていきましょう。

https://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B5%A1%E8%A9%95%E4%BE%A1

「≪左辺≫ ≪論理演算子≫ ≪右辺≫」というような、論理演算子による式(論理演算子式)があるとする。左辺(第一引数)を評価した段階で式全体の値が定まらない場合のみ右辺(第二引数)を評価する、というのが短絡評価である。

端的には「左辺値+論理演算子、で、値が決定しなければ右辺値を見に行くけど、右辺値をみるまでもなければ、左辺値は見に行かないよ~」と言っています。

左辺値がfalseで論理演算子がAND(&&)なら、右辺がtureだろうがfalseだろうが、false確定です。

左辺値がtrueで論理演算子がOR(||)なら、右辺値がtrueだろうがfalseだろうが、true確定です。

こういった時に「右辺値がcallされない」という動きを、PHPは、します。
これが「短絡評価」です。
便利でもあるのですが落とし穴にもなりやすいので、少し意識をしておきましょう。

便利なのは、例えばこんなコード。

if ( (isset($array['key']))&&('' !== $array['key']) ) {

これですが

if ('' !== $array['key']) {

だけだと「そもそもkeyがない時」に、Noticeが出てきてしまいますので、上述のように「いったんissetで確認」をします。
んで、そのときに「そもそもissetがfalseなら、右辺値が評価されない(から$array['key']にアクセスをしないからNoticeが出ない)」という動きになって、エラーを出すこともなく、恙なく処理が進みます。

こういった際に、もしかしたら「無意識に上述のような書き方をしているのかもしれない」ですが、とても便利な挙動をしてくれます。

ただ一方で「とりあえず関数は実行しておきたい、んで戻り値での評価もしておきたい」といった場合に。
例えば間違えて以下のように書くと、左辺値によっては「"とりあえず実行したい"関数が実行されない」という悲劇を生み出します。

function hoge()
{
    echo "call hoge\n";
    return true;
}

$a = 10;
$b = 10;

if ( ($a === $b)||(true === hoge()) ) {
    echo "true\n";
}

こんな風に、短絡評価は「便利であることが多い」反面、ある程度書けるようになって「こうやったらもっと効率的だ!!」と考える頃に、一度、がっつりとはまりやすい落とし穴にもなる仕様、になります。

このあたり、しっかりと踏まえて「ワンランク上のPHPer」を目指して頑張っていただければ、と思います。


この記事が気に入ったらサポートをしてみませんか?