title=演算子式


  * [[ref:assign]]
  * [[ref:selfassign]]
  * [[ref:multiassign]]
  * [[ref:range]]
  * [[ref:range_cond]]
  * [[ref:and]]
  * [[ref:or]]
  * [[ref:not]]
  * [[ref:cond]]

例:

          1+2*3/4

プログラミングの利便のために一部のメソッド呼び出しと制御構造は演算子形
式をとります。Rubyには以下にあげる演算子があります。

          高い   ::
                 []
                 +(単項)  !  ~
                 **
                 -(単項)
                 *  /  %
                 +  -
                 << >>
                 &
                 |  ^
                 > >=  < <=
                 <=> ==  === !=  =~  !~
                 &&
                 ||
                 ..  ...
                 ?:(条件演算子)
                 =(+=, -= ... )
                 not
          低い   and or

左の「高い」「低い」は演算子の優先順位です。
例えば「&&」は「||」より優先順位が高いので、以下のように
解釈されます。

    a && b || c   #=> (a && b) || c
    a || b && c   #=>  a || (b && c)

ほとんどの演算子は特別な形式のメソッド呼び出しですが、一部の
ものは言語に組み込みで、再定義できません。

: 再定義できる演算子(メソッド)

  +@, -@ は単項演算子 +, - を表しメソッド定義
  などではこの記法を利用します。


//emlist{
    |  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
    +  -  *  /    %   **   ~   +@  -@  []  []=  `
//}
  これらの演算子式の定義方法については[[ref:d:spec/def#operator]]を参照してください。

:再定義できない演算子(制御構造)

  演算子の組合せである自己代入演算子と !=, !~
  も再定義できません。
//emlist{
    =  ?:  ..  ...  !  not  &&  and  ||  or  ::
//}

===[a:assign] 代入

例:

          foo = bar
          foo[0] = bar
          foo.bar = baz

文法:

          変数 '=' 式
          定数 '=' 式
          式`['expr..`]' '=' 式
          式`.'識別子 '=' 式

代入式は変数などに値を設定するために用いられます。代入はロー
カル変数や定数の宣言としても用いられます。代入式の左辺は以
下のいずれかでなければなりません。

: 変数
//emlist{
            変数 `=' 式
//}
  左辺値が変数の場合、式を評価した値が変数に代入されます。


: 配列参照
//emlist{
            式1`[' 式2 ... `]' `=' 式n
//}
  式1を評価して得られるオブジェクトに対しての、式 2 から式 n までを
  引数とする []= メソッド呼び出しに変換されます。

  例:

            class C
              def initialize
                @ary = [0,1,2,3,4,5,6,7]
              end
              def [](i)
                @ary[i * 2]
              end
              def []=( i, v )
                @ary[i * 2] = v
              end
            end
            c = C.new
            p c[3]      # c.[]( 3 )  に変換され、その結果は 6
            p c[3] = 1  # c.[]=(3,1) に変換され、その結果は 1

: 属性参照
//emlist{
            式1 `.' 識別子 `=' 式2
//}
  式 1 を評価して得られるオブジェクトに対して、
  識別子= というメソッドを、式 2 を引数にして呼び出します。

  例:
//emlist{
            class C
              def foo
                @foo
              end
              def foo=( v )
                @foo = v
              end
            end
            c = C.new
            c.foo = 5   # c.foo=( 5 ) のように変換される
            p c.foo     # => 5
//}
  属性は [[m:Module#attr]] を使って同じように定義できます。

  例:
//emlist{
            class C
              attr :foo, true
            end
            c = C.new
            c.foo = 5   # c.foo=( 5 ) のように変換される
            p c.foo     # => 5
//}
====[a:selfassign] 自己代入

例:

          foo += 12       # foo = foo + 12
          a ||= 1         # a が偽か未定義ならば1を代入。初期化時のイディオムの一種。

文法:

          式1 op= 式2     # 式1は通常の代入の左辺のいずれか

op は以下のいずれかです。演算子と=の間にスペースを
空けてはいけません。

          +, -, *, /, %, **, &, |, ^, <<, >>, &&, ||

この形式の代入は
      式1 = 式1 op 式2
と評価されます。ただし、op が &&, || の場合には、
      式1 op (式1 = 式2)
と評価されます。この違いは属性参照のときに
      obj.foo ||= true
が、
      obj.foo = obj.foo || true
でなく
      obj.foo || (obj.foo = true)
と呼ばれることを示します。(obj.foo= は obj.foo の結果によって呼ばれな
いかも知れません)

====[a:multiassign] 多重代入

例:

          foo, bar, baz = 1, 2, 3
          foo, = list()
          foo, *rest = list2()

文法:

          式 [`,' [式 `,' ... ] [`*' [式]]] = 式 [, 式 ... ][`*' 式]
          `*' [式] = 式 [, 式 ... ][`*' 式]

多重代入は複数の式または配列から同時に代入を行います。左辺の
各式はそれぞれ代入可能でなければなりません。右辺の式が一つし
か与えられなかった場合、式を評価した値は配列に変換されて、各
要素が左辺のそれぞれの式に代入されます。左辺の要素の数よりも
配列の要素の数の方が多い場合には、余った要素は無視されます。
配列の要素が足りない場合には対応する要素の無い左辺には
nil が代入されます。

左辺の最後の式の直前に * がついていると、対応する
左辺のない余った要素が配列として代入されます。余った要素が
無い時には空の配列が代入されます。

例:

          foo, bar = [1, 2]       # foo = 1; bar = 2
          foo, bar = 1, 2         # foo = 1; bar = 2
          foo, bar = 1            # foo = 1; bar = nil

          foo, bar, baz = 1, 2    # foo = 1; bar = 2; baz = nil
          foo, bar = 1, 2, 3      # foo = 1; bar = 2
          foo      = 1, 2, 3      # foo = [1, 2, 3]
          *foo     = 1, 2, 3      # foo = [1, 2, 3]
          foo,*bar = 1, 2, 3      # foo = 1; bar = [2, 3]


多重代入は括弧により、ネストした配列の要素を代入することもできます。

          (foo, bar), baz = [1, 2], 3       # foo = 1; bar = 2; baz = 3

特殊な形式の代入式も多重代入にすることができます。

            class C
              def foo=( v )
                @foo = v
              end
              def []=(i,v)
                @bar = ["a", "b", "c"]
                @bar[i] = v
              end
            end

            obj = C.new
            obj.foo, obj[2] = 1, 2     # @foo = 1; @bar = ["a", "b", 2]

左辺が `,' で終る場合や、`*' の直後の式を省略した場合にも
余った要素は無視されます。

例:

          foo,*    = 1, 2, 3      # foo = 1
          foo,     = 1, 2, 3      # foo = 1
          *        = 1, 2, 3

特に最後の単体の `*' はメソッド呼び出しにおいて引数を完全に無視
したいときに使用できます。(メソッド呼び出しの引数の受け渡しは
多重代入とほぼ同じルールが適用されます)

例:
        def foo(*)
        end
        foo(1,2,3)

多重代入の値は配列に変換された右辺です。

===[a:range] 範囲式

例:

          1 .. 20
          /first/  ...  /second/

文法:

          式1 `..' 式2
          式1 ` ... ' 式2

条件式以外の場所では式1から式2までの範囲オブジェクトを返しま
す。範囲オブジェクトは[[c:Range]]クラス
のインスタンスです。 ... で生成された範囲オブジェクトは
終端を含みません。

====[a:range_cond] 条件式としての範囲式

条件式として範囲式が用いられた場合には、状態を持つ sed や awk 由来の
特殊な条件式として振る舞います。

「..」の場合:

 (1) 初期状態では式1だけを評価し、式1が真を返すまでは false を返します。
 (2) 式1が真を返すと true を返します。式2が真なら初期状態に戻ります。
 (3) この後は式2だけを評価し、式2が真を返すまで true を返します。
 (4) 式2が真を返すと true を返したあと、初期状態に戻ります。

「...」の場合:
 (1) 初期状態では式1だけを評価し、式1が真を返すまでは false を返します。
 (2) 式1が真を返すと true を返します。
 (3) この後は式2だけを評価し、式2が真を返すまで true を返します。
 (4) 式2が真を返すと true を返したあと、初期状態に戻ります。

例:

 # よくある使いかた

 5.times{|n|
   if (n==2)..(n==3)
     p n
   end
 }
 #=> 2
     3

 5.times{|n|
   if (n==2)...(n==3)
     p n
   end
 }
 #=> 2
     3

 # 「..」と「...」の違いを示すためだけの例
 
 5.times{|n|
   if (n==2)..(n==2)
     p n
   end
 }
 #=> 2
     
 5.times{|n|
   if (n==2)...(n==2)
     p n
   end
 }
 #=> 2
     3
     4

===[a:and] and

例:

          test && set
          test and set

文法:

          式 `&&' 式
          式 `and' 式

まず、左辺を評価して、結果が真であった場合には右辺も評価しま
す。and は同じ働きをする優先順位の低い演算子です。

and を伴う式をメソッドの引数に渡す場合は二重に括弧が必要となります。

        p(true && false)    #=> false
        p((true and false)) #=> false

===[a:or] or

例:

          demo || die
          demo or die

文法:

          式 `||' 式
          式 or 式

まず左辺を評価して、結果が偽であった場合には右辺も評価します。
or は同じ働きをする優先順位の低い演算子です。

or を伴う式をメソッドの引数に渡す場合は二重に括弧が必要となります。

        p(false || true)    #=> true
        p((false or true)) #=> true

===[a:not] not

例:

          ! me
          not me
          i != you

文法:

          `!' 式
          not 式

式の値が真である時偽を、偽である時真を返します。

          式 `!=' 式

!(式 == 式)と同じ。

          式 `!~' 式

!(式 =~ 式)と同じ。

not を伴う式をメソッドの引数に渡す場合は二重に括弧が必要となります。

        p(! false)      #=> true
        p((not false))  #=> true

===[a:cond] 条件演算子

例:

           obj == 1 ? foo : bar

文法:

           式1 ? 式2 : 式3

式1の結果によって式2または式3を返します。

           if 式1 then 式2 else 式3 end

とまったく同じです。
