問題
例えば、以下のコード、直感的には$hoge
が真なら$hoge
が返り、偽の場合は$fuga
が返ると思いますよね?
return $hoge or $fuga;
実際には以下のように解釈され、常に$hoge
が返ることとなります。
(return $hoge) or $fuga;
この問題5.20から警告が出るようになったので、気づけるのですが、それ以前だと見逃してる可能性があります。 まあ実際5.20使ってみてから問題があるコードを見つけたのですが。
perl5200delta - perl v5.20.0 での変更点 - perldoc.jp
で、これを実際にDeparseしてみるとこんな感じですね。
% perl -MO=Deparse,-print -e 'return $hoge or $fuga' $fuga unless return $hoge;
解決策
解決方法としては、括弧使うか、||
を使ってください。
return ($hoge or $fuga); # or return $hoge || $fuga;
% perl -MO=Deparse,-print -e 'return $hoge || $fuga' return $hoge || $fuga; % perl -MO=Deparse,-print -e 'return ($hoge or $fuga)' return $hoge || $fuga;
そんな感じ。 演算子の優先度はちゃんと意識しないとね。
ついーと
演算子の優先順位 むつかしい
— masasuzu 🍶🐫 (@masasuz) 2018年7月27日
return $aaa or $bbb; って$aaaが偽なら$bbbが返ってくると思うじゃないですか。
— masasuzu 🍶🐫 (@masasuz) 2018年7月27日
ところが常に$aaaが返ってくるんですよ。5.20まで警告が出ないから気がつかなかったという話。(社内モジュールでそういうのがあった)
優先度の問題ですね。
`Possible precedence issue with control flow operator`https://t.co/NcAy0oHVZC
— masasuzu 🍶🐫 (@masasuz) July 27, 2018
なので、
— masasuzu 🍶🐫 (@masasuz) 2018年7月27日
`return $aaa || $bbb`
とするか、
`return ($aaa or $bbb)`
とするのが正しい。らしい。
へー。またperlに詳しくなってしまった。
— masasuzu 🍶🐫 (@masasuz) July 27, 2018