Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rubyの単項演算子(+、-)の動作

あけましておめでとうございます。本年もTechRachoをよろしくお願いいたします。

年末年始はインフルエンザで完璧に寝正月になってしまったのですが、Rubyで小ネタを見つけたので記事にしてみました。
チェックにはRuby 2.5を使いました。

Rubyの単項演算子(+、-)の動作

基本の動作

今さらですが、単項のIntegerやFloatの前に付く+-はそのまま数学記号の正符号、負符号とみなせます。この場合+は何もしないと解釈されるため、最終的に数学記号の慣習に沿って+はドロップされます。

1     #=>  1
+1    #=>  1
-1    #=> -1
1.0   #=>  1.0
+1.0  #=>  1.0
-1.0  #=> -1.0

+-が複数ある場合、解釈後に圧縮されます。これは間にスペースがあっても同じです。

-+-- ++- -+ 1  #=> -1

2項演算でも同様です。

-1 -+-- ++- -+ 1 #=> -2

こんな書き方は誰もしませんが、数学記号としての正負符号の挙動が担保されていることがわかります。

この挙動は?

今回気づいたのは以下の挙動でした。

まず、丸かっこ()はあってもなくても単項演算子の解釈に違いはありません。

-(-1) #=>  1
+(-1) #=> -1

classメソッドでクラスを調べることもできます。

-1.class #=> Integer
+1.class #=> Integer

しかし、丸かっこの外に単項演算子がある状態でclassを取ってみると次のようになりました。

-(-1).class #=> NoMethodError: undefined method `-@' for Integer:Class
+(-1).class #=> NoMethodError: undefined method `+@' for Integer:Class

当初はおやっと思いましたが、(-1).classが先に解釈され、続いて戻り値Integerに対して単項演算子-が適用されたことにやっと気づきました。

この挙動を回避するには、丸かっこをさらに追加します。

(-(-1)).class #=> Integer
(+(-1)).class #=> Integer

これは変数などに対しても同様です。

a = 1
-a.class    #=> NoMethodError: undefined method `-@' for Integer:Class
(-a).class  #=> Integer

おまけ: 文字列結合の+

ついでながら、文字列結合演算子としての+も連続して置くことができます。

"a" + + "a" #=> "aa"

なお、文字列結合は原則として+ではなく式展開"#{}"を使いましょう。

Rubyの文字列連結に「#+」ではなく式展開「#{}」を使うべき理由

関連記事

Ruby: ぼっち演算子`&.`の落とし穴(翻訳)

【保存版】Rubyスタイルガイド(日本語・解説付き)総もくじ


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。