2789


まったく実践的じゃない質問です。

単なる好奇心からインクリメント演算子を何気なくいじって、結果がどうなるか試していました。

すると正負をひっくり返した場合にエラーが出る場合と出ない場合がありました。

`+--+`を前置した場合:

[code]

    $ perl -E '$z = 3; say +--+$z;'
    2
    
[/code]

`-++-`を前置した場合:

[code]

    $ perl -E '$z = 3; say -++-$z;'
    Can't modify negation (-) in preincrement (++) at -e line 1, near "$z;"
    Execution of -e aborted due to compilation errors.
    
[/code]

どうしてこのような差が出るんでしょうか？

perlのバージョンは5.18.2、OSXの上で実行しています。

* * *

以下はMO=Deparseした時の出力です:

[code]

    $ perl -MO=Deparse -E '$z = 3; say +--+$z;'
    use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
    $z = 3;
    say --$z;
    -e syntax OK
    
    $ perl -MO=Deparse -E '$z = 3; say -++-$z;'
    Can't modify negation (-) in preincrement (++) at -e line 1, near "$z;"
    -e had compilation errors.
    use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
    $z = 3;
    say -++(-$z);
    
[/code]


CC BY-SA 3.0
2014-12-29T09:38:17.173
2787
2014-12-29T13:27:03.710
62
question
perl
インクリメント演算子の+と-は実装が大きく異なっているのでしょうか？


`MO=Deparse`の出力を見ての推測での回答になりますが、
インクリメント演算子の違いではなく単体の`+`と`-`が先頭についた時の処理の違いではないでしょうか？

通常、インクリメント演算子の前に他の演算子を置くことはできませんが、
先頭に`+`がついた場合は第一にそれが無視され残りの演算を行うためインクリメントが正常に行われるのだと思われます。


CC BY-SA 3.0
2014-12-29T09:57:03.507
2789
2014-12-29T09:57:03.507
3271
2787
answer


コメントに書こうかと思ったのですが、長すぎたのでこちらに。尚、`perl`は普段全くかじっておりません。。

[code]

    $z = 3; say ++(-$z);
    
[/code]

でも同様のエラーが出ます。ここで

[code]

    ++(-$z)
    
[/code]

の部分は実質

[code]

    -$z = -$z + 1;
    
[/code]

となるんだと思いますが、この文ではやはり`Can't modify negation in scalar
assignment`というエラーが出ます。単純に構文エラーが気がするので、そのせいではないでしょうか。

* * *

それに対して、

[code]

    +--+$z
    
[/code]

の場合ですが

[code]

    +$z = +$z + 1;
    
[/code]

という文は問題なく動作します。

[code]

    +(--(+$z))
    
[/code]

すなわち

[code]

    --$z
    
[/code]

と解釈され、問題なく実行されているのだろうと考えます。


CC BY-SA 3.0
2014-12-29T09:58:26.757
2790
2014-12-29T09:58:26.757
3313
2787
answer


単項演算プラス(unary +) と 単項演算マイナス (unary -)では根本的に扱われ方が違います。[Perl Docmentation の
Unary-Operators](http://perldoc.perl.org/perlop.html#Symbolic-Unary-Operators)
を参照してください。

単項演算マイナスは、Perl では、数字らしきものに付けられれば、符号を反転する意味になります。

一方、単項演算プラスは、演算上、何の意味もないです。「正の数を表す」といった意味はなく、数式に関係のないものです。飾りですらありません。演算子と呼ぶのも不適切かもしれません。（ない、といっても、[修飾子のない文字列(bareword)の意味が曖昧なところで
+ をつける](http://modernperlbooks.com/books/modern_perl/chapter_11.html)と、
それが、スカラ式やキーワードであると優先的に解釈されるようです。）

例えば、

`+` は以下のように様々ところで付けることができ、それは処理に影響を与えません:

[code]

    perl -e '$s = 3; print "AAA" .  .123 . $s . "\n";
    => AAA0.1233
    perl -e '+$s = +3; +print +"AAA" .  +.123 . +$s . +"\n";
    => AAA0.1233
    
[/code]

`-` は値評価に影響を与えないような使い方がほぼできません:

[code]

    perl -e '$s = -3; -print -"AAA" .  -.123 . -$s . -"\n";'
    => -AAA-0.12330
    perl -e '-$s = 3;'
    ==> パースエラー
    perl -e 'print +print;
    => 1
    perl -e 'print -print;
    => -1
    
[/code]

単項演算プラスは、Perl が
修飾子なしの文字列(bareword)がなにかを知る判断材料にしか使われないので、数式の評価前には消滅しているとみてよいでしょう。今回の場合であると、単項演算プラスが消滅した後の
`++-` という表現がNGであったということが問題でした。（評価される前のマイナス記号に対して Auto-Increment
をすると判断された。またマイナスが評価された後だとしても、定数に対しての `++` はできない。）

参考 : [Perl Documentation - Symbolic Unary
Operators](http://perldoc.perl.org/perlop.html#Symbolic-Unary-Operators)


CC BY-SA 3.0
2014-12-29T13:27:03.710
2799
2014-12-29T13:27:03.710
4978
2787
answer