2つの論理和演算子の優先順位について(|| と or)
なんとなく、はてなにメモするのがいいかなと思ったので、今日確認したことを。コメントに書いた説明が正確かどうか不安もあるけど。
今回わかったことは
... sub property { my $self = shift; $self->{'_arg'} = shift || return $self->{'_arg'}; } ...
で set/get みたいな効果になるけど、このまま || を or に変えるとうまくいかないということ(実際は shift する/した値の内容もチェックしたほうがいいかも)。「制御構造には || でなく or を使う」と単純に理解していたので少し理解に苦しんだものの、代入演算子 = に対する両者の優先度の違いを確認してなんとか飲み込めた。
- perlop - Perl operators and precedence - perldoc.perl.org
- perlop - Perl の演算子と優先順位 - perldoc.jp
test_perlop.pl*1
{ package test_perlop; use strict; use warnings; # or は = より優先度が低く、 # || は = より優先度が高いことを確認する。 my $undef = undef; my $str = 'str'; my $v1; $v1 = $undef || $str; my $v2; $v2 = $undef or $v2 = $str; printf " \$v1 = %s\n", $v1; printf " \$v2 = %s\n", $v2; # or の場合: # $arg=shift が評価された後に return $arg が評価されるので # $arg には shift された undef が代入され、それが返される。 sub hoge { my $arg = 'hoge'; $arg = shift or return $arg; } # || の場合: # $arg = shift が評価される前に shift || return ... が評価される、 # すなわち shift が偽となると即 return $arg が評価され # shift からの代入は行われないので $arg の内容は 'foo' のまま返される。 sub foo { my $arg = 'foo'; $arg = shift || return $arg; } printf " \$hoge = %s\n", &hoge; # (1) printf " \$foo = %s\n", &foo; my $op = PerlOp->new; printf " \$op->foo = %s\n", $op->foo; # (2) printf " \$op->bar = %s\n", $op->bar; } { package PerlOp; use strict; use warnings; sub new { my $pkg = shift; bless{foo => 'foo', bar => 'bar'}, $pkg; } sub foo { my $self = shift; $self->{foo} = shift or return $self->{foo}; } sub bar { my $self = shift; $self->{bar} = shift || return $self->{bar}; } 1; } __END__ =pod 出力 (ActivePerl v5.8.8 で確認) : > perl test_perlop.pl $v1 = str $v2 = str Use of uninitialized value in printf at test_perlop.pl line 23. $hoge = $foo = foo Use of uninitialized value in printf at test_perlop.pl line 27. $op->foo = $op->bar = bar (1) と (2) の位置で Use of uninitialized value... と警告される =cut
*1:行数節約スタイル。普段はこんな書き方しません。