Ruby TIPS

Ruby TIPS

文の途中で改行する/if文も値を返す ― コーディングミスを防ぐには?(1)

2015年12月16日

Rubyプログラミングでミスしやすい意外な落とし穴を紹介。「式の取り扱い」に関して、改行で陥りやすいワナやif文などの制御構造が返す値を取り上げる。

ローグ・インターナショナル 羽山 博
  • このエントリーをはてなブックマークに追加

 Rubyには他のプログラミング言語にはない便利な機能が数多く備わっている。一方で意外な落とし穴もある。本稿では、基本の基本ともいえる式の取り扱いをテーマに、気づきにくいミスを防ぐ方法を見ていく。

文の途中で改行する

 Rubyでは、基本的に改行が文の区切りとなる。そのため、

式の途中で改行すると、1つの式だと思っていたものが複数の式と見なされてしまう

ことがある。エラーにもならず、期待した結果に近い値が求められてしまって、誤りに気付かないことも多い。そういった誤りを分かりやすい例で見てみよう。

Ruby
sum = 0
for i in 0..99
  sum = sum
         + i
end
puts sum
リスト1.1 うまく動かない例(sample001a.rb)

0から99までの値を合計する単純なプログラム。sum = sum + iという式の途中で改行した。putsメソッドでsumの値を出力すると……。

 実行例は以下の通り。

コンソール
$ ruby sample001a.rb 
0
リスト1.2 リスト1.1の実行例

4950となるはずの結果が0になってしまった。

 期待した結果にならないのは、途中で改行したため「sum = sum」という式と「+ i」という式があると見なされたからである。変数sumsumの値を代入すればもちろんsumの値は変わらない。「+ i」はiの値を返すが、ただ値を返すだけで全く利用されていない。

 正しいコードを書くには、式を完成させない状態で改行するか(リスト1.3)、改行したい位置に\*1を入力すればよい(リスト1.4)。

  • *1 \はバックスラッシュで、ASCII文字コードは0x5Cとなる。
    ●Windows/Linux環境では\¥は同じ文字コードで、日本語キーボードの¥キーで入力できる。
    ●Macの日本語キーボードでは、¥キーを押すと、基本的にASCII文字コード0xA5の円記号が入力されてしまう(ただしターミナルでは基本的にバックスラッシュが入力される)。Macバックスラッシュを入力するには、option¥キーを押せばよい。間違えないように注意してほしい。
Ruby
sum = 0
for i in 0..99
  sum = sum +
         i
end
puts sum
リスト1.3 式を完成させない状態で改行した例(sample001b.rb)

+などの演算子を行末に書けば、式が完結していないので、次の行に続くと見なされ、正しい結果が得られる。

Ruby
sum = 0
for i in 0..99
  sum = sum \
         + i
end
puts sum
リスト1.4 改行したい位置に\を入力した例(sample001c.rb)

行末に\(=¥)を入力すれば、改行が取り消されるので、行が継続しているものと見なされる。このコードでも正しい結果が得られる。

 この例はあまりにも単純なので、誤りにも気づきやすいが、式が複雑で長いものになったり、加算する値が他の値に比べて小さかったりすると、見過ごしてしまう可能性も高い。式を1行に収めてしまえばこのような問題は起こらないが、コードの可読性を高めるために途中で改行したいときもあるだろう。そういった場合の落とし穴なので注意してほしい。

【文法】自己代入演算子

 Rubyでは+=-=などの自己代入演算子が使える。リスト1.3や1.4のコードなら以下のように書ける。

Ruby
sum += i

 自己代入演算子として演算子は以下の通り。

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

 なお、インクリメント/デクリメントを行う演算子はないことに注意。他のプログラミング言語にある++--は使えない。

if文も値を返す

 Rubyのプログラムは式の集まりである。一般に、はリテラルや変数、関数呼び出し、さらにそれらを演算子でつなぎ合わせたものだが、Rubyではifwhileなどの制御構造も式となる。そして、

ほとんどの式が値を返す

例えば、ifも式の値を返すので、以下のようなコードも書ける。

Ruby
x = rand(0..10)
a = if x % 2 == 0 then "even" else "odd" end
puts a
リスト2.1 値を返すif文の例(sample002a.rb)

0以上10未満の乱数を作成し、それが偶数か奇数かを判定するプログラム。%は剰余(=余り)を求める演算子。2で割った余りが0なら"even"という文字列を返し、そうでなければ"odd"を返す。

 念のため、実行例も示しておこう。

コンソール
$ ruby sample002a.rb
odd
リスト2.2 リスト2.1の実行例

この例では、作成された乱数が奇数だったのでoddと表示された。

【文法】条件演算子

 条件演算子?を使えば、単純な条件分岐が簡単に書ける。形式は「条件式?条件式がtrueのときに値を返す式:条件式がfalseのときに値を返す式」となる。リスト2.1のコードなら以下のように書ける。

Ruby
a = x % 2 == 0 ? "even" : "odd"

 なお、forは指定した範囲を返し、whilenilを返す。あまり意味のないプログラムだが、以下のように書くこともできる。

Ruby
sum = 0
x = for i in 0..99
      sum = sum + i
end
puts x
Ruby
sum = 0
i = 0
x = 0
x = while i < 100
      sum = sum + i
      i = i + 1
end
p x
リスト2.3 上:値を返すfor文の例(sample002b.rb)、下:値を返すwhile文の例(sample002c.rb)

上のプログラムを実行すると、forが返した値が表示される。結果は0..99となる。なお、「..」は範囲を表す演算子である。
下のプログラムを実行すると、whileが返した値が表示される。結果はnilとなる。出力にputsメソッドを使うとnilの場合に値が表示されないので、pメソッドを使っている。

まとめ

 Rubyでは、式の途中で改行すると、期待した結果が得られない場合がある。改行が必要な場合は、演算子が行末になるようにするか、行末に\を入力するとよい。

 また、ほとんどの式は値を返す。ifforなども値を返す。

処理対象:改行 カテゴリ:文法 > 字句構造
処理対象:文|式|値を返す式 カテゴリ:文法 > プログラム/文/式
処理対象:if文 カテゴリ:文法 > 制御構造 > 条件分岐
処理対象:for文|while文 カテゴリ:文法 > 制御構造 > 繰り返し

※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

1. Rubyとは? ― オブジェクト指向のスクリプト言語

Rubyとは何か。入門者向けに、その概要と特徴を紹介し、基本的な文法を使った簡単なコード例を示す。

2. 【現在、表示中】≫ 文の途中で改行する/if文も値を返す ― コーディングミスを防ぐには?(1)

Rubyプログラミングでミスしやすい意外な落とし穴を紹介。「式の取り扱い」に関して、改行で陥りやすいワナやif文などの制御構造が返す値を取り上げる。

3. 関数で複数の返り値を返す/関数の引数は値渡し ― コーディングミスを防ぐには?(2)

Rubyプログラミングでミスしやすい意外な落とし穴を紹介。関数を使って複数の値を返す方法と、引数による値の受け渡しに関するポイントを説明する。値渡しの関連として、非破壊的な変更と破壊的な変更についても取り上げる。

4. Rubyをインストール/アップデートするには?(Windows編)

Windows上でのRubyプログラミングを始める入門者向けに、Ruby環境の構築方法、複数バージョンのインストール方法、バージョンのアップデート方法を説明する。

5. 代入により決まる変数のデータ型/丸め誤差が発生する浮動小数点数の比較― コーディングミスを防ぐには?(3)

初心者向けにRubyプログラミングの落とし穴を紹介。代入する値により変数のデータ型が決まることに関する注意点と、浮動小数点数の比較における丸め誤差の問題と回避方法について説明する。

イベント情報(メディアスポンサーです)

Twitterでつぶやこう!


Build Insider賛同企業・団体

Build Insiderは、以下の企業・団体の支援を受けて活動しています(募集概要)。

ゴールドレベル

  • グレープシティ株式会社
  • 日本マイクロソフト株式会社