C言語やPHPでプログラミングを学んだ方がRubyを使い始めて戸惑うことの1つが、インクリメント演算子「++」を使うとエラーになる点です。使い慣れた書き方ができないことに納得できない、と感じる方もおられるでしょう。
今回はインクリメント演算子の機能と、Rubyにおけるインクリメント演算子の代わりの記述方法について解説します。
Rubyではインクリメント演算子が使えない
Rubyでは、C言語やPHPなど他のプログラム言語で使えるインクリメント演算子「++」が使えません。もし、Rubyのプログラムの中でインクリメント演算子を使ってしまうとエラーになるので注意が必要です。
なお、インクリメント演算子とは何かを知らない方のために、インクリメント演算子の基本について解説します。
インクリメント演算子とは
インクリメント演算子とは、「+」記号を2つ並べた「++」を使い、変数の値を1つ増やす演算子です。演算によって元の変数を変更してしまうので、Rubyの表現では破壊的な演算子と言えます。
なお、インクリメント演算子が使えるプログラミング言語としてC言語が有名であり、PHPやJavaなどのC言語の影響受けた多くのプログラミング言語で利用できます。
PHPのインクリメント演算子の例
x = 1; x++; print x . "\n"; /* 2が表示される */
元々インクリメントはCPUの機能
C言語の文法は開発に使われたコンピュータのCPUで使われる命令の影響を受けています。そして、CPUの命令には「レジスタの内容を1増やす」という命令があり、これをC言語で使えるようにしたのがインクリメント演算子です。
知らない方のために簡単に解説すると、CPUは、メモリーのアドレスから順に命令を読み込みます。そしてアドレスに1を加える機能がCPUには備わっており、その機能をレジスタに適用したのが「レジスタの内容を1増やす」という命令です。
つまり今回紹介するインクリメントとはCPUにとって基本的な機能の1つです。そしてCPUを直接操作するプログラムを記述できるC言語では、繰り返し処理やポインターの操作など、いろいろな場面でインクリメントを利用します。
Rubyではインクリメント演算子が使えない
先ほど紹介したC言語のインクリメント演算子は、そのままCPUの命令に変換されて動作します。そしてC言語と同じようにプログラムをCPUの命令に変換するプログラム言語では、インクリメント演算子を同じように変換します。
しかしRubyはスクリプト言語のため、直接CPUの命令に変換する必要はありません。さらにRubyのプログラムは全ての変数がオブジェクトとして扱われます。数字も例外ではありません。整数を扱う変数に1を加える場合、C言語のように変数という箱の中身を書き換える訳ではなく、変数のオブジェクトの参照先を計算結果後の数字に置き換えます。
したがってRubyでは変数を破壊的に変えてしまうインクリメント演算子は使用できず、代入を伴う演算方法を利用してください。
Rubyで変数に1を加えるなら
先ほど紹介したように、RubyではC言語などで使えるインクリメント演算子「++」は使えません。では代わりにどのように記述すればいいのでしょうか。
次にインクリメント演算子の代わりに使える方法を紹介します。
自己代入演算子を使う
変数にある数字を加えた結果を、同じ変数に代入する処理でよく使われるのが自己代入演算子です。インクリメント演算子が変数に1を加える処理なので、同じ処理を自己代入演算子で記述できます。
数値を格納した変数に1を加える例
x = x + 1;
自己代入演算子で変数に1を加える例
x += 1
このうち「+=」は自己代入演算子と呼ばれる機能で、+=演算子の右側の数字を変数に加算します。自己代入演算子は、演算だけではなく代入を伴う処理という点に注目してください。
Integerクラスのnextメソッドを使う
整数を扱うIntegerクラスのnextメソッドは、整数を格納した変数に使用することでその数の次の値を返します。そして、nextメソッドが返した数を元の変数に代入してやると、インクリメント演算子のように使えます。
Integerクラスのnextメソッドの例
x = 1 x = x.next puts x # 2が表示される
なお、Integerクラスのsuccメソッドはnextメソッドの別名で、その機能は同じです。
Integerクラスのsucctメソッドの例
x = 1 x = x.succ puts x # 2が表示される
代わりの機能を使う際の注意点
Rubyではインクリメント演算子が使えないので、変数に1を足したり、次の数字に切り替えるnextメソッドを使い、その結果を元の変数に代入します。しかし、このような処理は、変数が整数に限られるケースです。
例えば、PHPは文字と数字を意識しないで変数を利用できます。しかし、Rubyは変数の宣言は不要ですが、実行時に自動的にどのクラスに所属するかを決めてから処理します。そのため、PHPなら次のように変数の型を意識せずにインクリメント演算子を使用できますが、Rubyは型を意識してプログラムを書かなければなりません。
PHPで文字の数字にインクリメントする例
<?php $a = "1"; $a++; print $a . "\n"; /* 2が表示される */ ?>
Rubyで文字の数字を整数に変換してインクリメントする例
a = '1' a = a.to_i + 1 puts a # 2が表示される
上記のRubyのプログラムでは当初変数aに’1’を格納したことで文字列のオブジェクトで作られます。次に1を加算する際a.to_iで数字に変換し、1を加算して元の変数aに代入します。なお、代入した時点で変数aは数字のオブジェクトに変更されています。
Rubyでインクリメント演算子を使わない工夫
Rubyはオブジェクト指向のプログラム言語であり、他のプログラム言語とは違った使い方が可能です。そのため必ずしもインクリメント演算子を必要とせずに繰り返し処理を書くことが可能です。ぜひ、そのようなRubyらしい使い方をマスターしてください。
次からそのようなインクリメント演算子を使わない工夫を紹介します。
配列に対して繰り返し処理を使わない
Ruby以外のプログラム言語では、よく繰り返し処理の中でインクリメント演算子が使われます。例えば配列の要素を扱う場合、添え字の数字をインクリメント演算子で1ずつ変更するといったケースです。
phpのインクリメント演算子で配列の要素を表示する例
<?php $arr = [1, 2, 3, 4, 5]; $i=0; while ($i < count($arr) ) { print $arr[$i] . "\n"; $i++; } ?>
このような処理をRubyで記述する場合、eachメソッドなどの配列を操作するメソッドを利用すればインクリメント演算子は不要です。
Rubyで配列の要素を表示する例
arr = [1, 2, 3, 4, 5] arr.each { |x| puts x }
Rubyでは範囲のオブジェクトが使える
Ruby以外のプログラム言語では、ある範囲内の数字を扱う場合でもインクリメント演算子が使われます。例えば1から10までの範囲で繰り返すケースです。
PHPで1から10までの数を合計するプログラムの例
<?php $i=1; $answer = 0; while($i <= 10) { $answer += $i; $i++; } print $answer . "\n";
Rubyでは範囲のオブジェクトが使えるので、繰り返し処理にする必要はありません。例えば上記の1から10までの合計を求めるだけなら、sunメソッドを使えば簡単に記述できます。
puts (1..10).sum
まとめ
これまで紹介したようにC言語やPHPなどで使えるインクリメント演算子「++」は、Rubyでは使用できません。これは代入を伴わない数字の演算がRubyではできないためで、代入を伴う「+=」自己代入演算子や、next演算子の結果を代入するなどしてください。
なおC言語やPHPなどではインクリメント演算子「++」を繰り返しの処理の中でよく使います。Rubyでは配列や数字の範囲で使える便利なメソッドがあるので、そのようなメソッドを利用すればインクリメント演算子は不要です。このようなメソッドを使ったRubyらしい書き方を利用してください。