Ruby TIPS
if修飾子/unless文/case文 ― ちょっと便利な条件分岐の構文とは?
Rubyには、if文のような一般的なもの以外にも、if修飾子/unless文/unless修飾子/case文といった便利な条件分岐の構文が用意されている。その基本的な使い方を解説。
Rubyでは、if
文やcase
文を使った一般的な条件分岐だけでなく、便利な条件分岐の構文がいくつか用意されている。今回は、他のプログラミング言語にはない、そういった便利な構文の使い方を見ていく。
if修飾子を利用する
if
文の一般的な書き方については後述のコラムを参照していただくこととして、if修飾子から見ていこう。if
修飾子は、以下の例のように、式の後ろに書く。if
修飾子に書かれた式がtrueのときだけ、前に書かれた式を実行する。
i = 10
p i if $DEBUG
|
$DEBUG
の値がtrueのときにはp i
を実行し、変数i
の値を出力する。
この書き方では、if
文が前に出てこないので、制御構造に関する記述に注意をそがれることが緩和できる。それにより、処理そのもの(=どんな式を実行するか)が多少なりとも追いかけやすくなる。プログラムをデバッグモードで実行するには、ruby
コマンドに-d
オプションまたは--debug
オプションを付けるとよい(実行例1.1)。
$ ruby sample001.rb
……何も表示されない……
$ ruby -d sample001.rb
Exception `LoadError' at /usr/local/Cellar/ruby/2.2.3/lib/ruby/2.2.0/rubygems.rb:1231 - cannot load such file -- rubygems/defaults/ruby
10
$
|
最初のruby
コマンドには-d
を付けていないので、何も表示されない。2番目のruby
コマンドのように-d
オプションを付けるとデバッグモードとなる。10という値が表示されていることが分かる。例外メッセージも表示されているが、これについては本文で説明する。
なお、デバッグモードではプログラムの中で適切に対処された例外に関してもメッセージが表示されるので、実行例1.1のようなエラーメッセージが表示される(この例はOS X 10.11.4上のRuby2.2.3p173での実行例であり、異なる環境では他のメッセージが表示されることがある)。ちなみに、上のメッセージはrubygems.rbファイル内で対処されている例外に関するものなので、特に気にする必要はない。
if
修飾子の前に複数の式を書きたいときには、begin
とend
で囲めばよい(リスト1.2)。
i = 10
begin
flg = true
p i
end if $DEBUG
|
$DEBUG
の値がtrueのときには変数flg
にtrueを代入し、変数i
の値を出力する
蛇足だが、begin ... end
も値を返す。返される値はbegin ... end
内の最後の式なので、リスト1.2の例であれば、p i
という式の値(つまり10)となる。
【コラム】if文の書き方
条件分岐はプログラミングの基本的な知識なので、初歩から解説することは避け、ここでは、if文の書き方と例を簡単にまとめておくにとどめる。
書き方1: 条件式の値がtrueのとき、式を実行する
then
は省略しても構わない。また、式は複数書いてもいい。ただし、改行せずに全てを1行で書くときにはthen
は省略できない。その場合、文は;
で区切る必要がある
- 例: 変数
age
の値が60未満なら、変数rank
に"一般"を代入し、変数rate
に0.2を代入する。そうでなければ、何もせず次に進む
if age < 60
rank = "一般"
rate = 0.2
end
|
上の例と同じ処理を1行で書いた場合
if age < 60 then rank = "一般"; rate = 0.2 end
|
書き方2: 条件式がtrueのとき、式1を実行し、そうでない場合、式2を実行する
この場合も、式1や式2は複数書ける。
- 例: 変数
age
の値が60未満なら、変数rank
に"一般"を代入し、変数rate
に0.2を代入する。そうでなければ、変数rank
に"シニア"を代入し、変数rate
に0を代入する
if age < 60
rank = "一般"
rate = 0.2
else
rank = "シニア"
rate = 0.0
end
|
式1や式2の部分にはさらにif
文を書くこともできる(if
のネスト)。その場合は、書き方3のようにelse
とif
をまとめて、elsif
と書ける。また、文の最後の複数のend
は1つにまとめられる
書き方3: 条件式1がtrueのとき、式1を実行し、そうでない場合で条件式2がtrueのとき、式2を実行する。elsif以下は複数書けるので、同様に評価していく。全ての条件に当てはまらない場合には式nを実行する
コード | フローチャート |
---|---|
if 条件式1 then
式1
elsif 条件式2 then
式2
:
else
式n
end
|
このフローチャートでは、見やすくするため、書き方1や書き方2とはtrueとfalseの流れを逆に描いてあることに注意。
- 例: 変数
age
の値が20未満なら、変数rank
に"ジュニア"を代入し、さらに変数rate
に0.5を代入する。そうでない場合で、変数age
の値が60未満なら、変数rank
に"一般"を代入し、変数rate
に0.2を代入する。そうでなければ変数rank
に"シニア"を代入し、変数rate
に0を代入する
if age < 20
rank = "ジュニア"
rate = 0.5
elsif age < 60
rank = "一般"
rate = 0.2
else
rank = "シニア"
rate = 0.0
end
|
unless文を利用する
if
文とは逆に、条件式がfalseのときに式を実行するには、unless文が使える。書き方は上のコラムでまとめたif
文の書き方とほぼ同じで、if
の代わりにunless
を書くだけ。ただし、コラムの書き方3で示したelsif
は使えない。これについても簡単な例を見ておこう。
age = ARGV[0].to_i
unless age >= 60 then
rank = "一般"
rate = 0.2
else
rank = "シニア"
rate = 0.0
end
puts rank,rate
|
unless
文では、条件式がfalseのときにthen
以下の式が実行される。条件式がtrueのときにはelse
以下の式が実行される。この例では、変数age
の値が60以上でなければthen
以下の式が実行され、そうでなければ(=変数age
の値が60以上であれば)、else
以下の式が実行される。
実行例は以下の通り。
$ ruby sample003.rb 18
一般
0.2
$ ruby sample003.rb 60
シニア
0.0
$
|
条件を満たしていないときに、then以下の文が実行されていることが分かる。
通常は、if
文だけでどのような条件分岐も表せるが、unless
文を使った方が、条件が自然に表せる場合もある。ただし、上の例のようにelse
まで指定する必要がある場合にはかえって分かりにくくなることの方が多いので、無理にunless
文を使うよりは素直にif
文を使った方がいい。
unless修飾子について
なお、最初に述べたif
修飾子と同様に、unless修飾子を書くこともできる。当然のことながら、その場合は、unless
の後に書いた式がfalseのときだけ、unless
の前の式が実行される。
case文の便利な使い方
他のプログラミング言語では、case文に相当する文(C言語やJavaのswitch
文など)は、ある変数の値によっていくつかに処理を分岐させるのに使うのが一般的である。Rubyでもそういった使い方はもちろんできるが、if
文による多分岐と同様に、さまざまな条件による分岐もできる。一般的な使い方の例を見た後で、もう一つの使い方を見てみよう。
area = ARGV[0].to_i
case area
when 0..3 then
area_name = "23区"
when 4 then
area_name = "多摩"
else
area_name = "その他"
end
puts area_name
|
case
の後に書いた式の値が、when
の後に書いた式の値に一致したとき、then
以下の式が実行される。それまでの全ての条件に一致しない場合には、最後のelse
の後の式が実行される。
case
文では、when
の後に範囲式(例えばリスト1.4の0..3
)を書いてもいい。また、then
以下の式を次の行に書く場合はthen
を省略しても構わない。ただし、when
の後で改行せず、同じ行に実行したい式を書く場合はthen
は省略できない。
では、実行結果を見ながら、処理の流れを確認しておこう。
$ ruby sample004.rb 0
23区
$ ruby sample004.rb 4
多摩
$ ruby sample004.rb 5
その他
|
コマンドライン引数の値は変数area
に代入される。変数area
の値が0、1、2、3のいずれかのときには、when 0..3
の場合に一致するので「23区」と表示される。4のときには「多摩」と表示され、それ以外のときは全て「その他」と表示される。
Rubyのcase
文では、case
の後の変数を省略すると、複数並ぶwhen
の後の式が最初にtrueになる場合のthen
以下の式が実行される。例を見てみよう。
以下の例では、変数age
(年齢)の値が10未満の場合には変数charge(料金)に0を代入し、変数stock
(株式の保有数)の値が1000以上の場合は変数charge
に300を代入する。それ以外の場合は変数charge
に500を代入する。
age = 20
stock = 2000
case
when age < 10
charge = 0
when stock >= 1000
charge = 300
else
charge = 500
end
puts charge
|
case
の後に式を書かない場合は、さまざまな変数の値を利用した多分岐の処理が実現できる。if
文をネストさせても同じことができるが、全ての条件式が同じカラムから書かれるので、条件式の並びが多少見やすくなる(ただし、elsif
の「そうでないとき」という意味合いが意識しづらいかもしれない)。
ここでは、変数age
の値と変数stock
の値をプログラムの中で決めているので、汎用性に欠けるが、取りあえず実行して、動作を確認してみよう。
$ ruby sample005.rb
300
|
この例では、変数age
の値が20、変数stock
の値が2000なので、最初のage < 10
はfalseになるが、次のstock >= 1000
がtrueになるので、「300」という結果が表示される。変数age
や変数stock
の値を変えて動作を確認してみよう。
最後に補足だが、if
文を使う場合でも、case
文を使う場合でも、falseとnil以外は全てtrueと見なされることにも注意しておく必要がある。
まとめ
Rubyでは、if
修飾子やunless
修飾子で指定した条件がtrueのときにのみ、その前に指定した式を実行するといった書き方ができる。また、case
文では1つの式の値による多分岐だけでなく、複数の式を使った多分岐の処理もできる。
※以下では、本稿の前後を合わせて5回分(第6回~第10回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
6. 桁区切り数値の記述と出力/文字列を逆順に/文字列の分割/文字列の各文字の利用 ― コーディングミスを防ぐには?(4)
初心者向けにRubyプログラミングの落とし穴を紹介。桁区切り指定で数値リテラルを記述する方法や、桁区切りの数値文字列を出力する方法、文字列を逆順に並べ替える方法、文字列を文字列で分割する方法、文字列を1文字ずつ扱う方法を説明する。
8. 【現在、表示中】≫ if修飾子/unless文/case文 ― ちょっと便利な条件分岐の構文とは?
Rubyには、if文のような一般的なもの以外にも、if修飾子/unless文/unless修飾子/case文といった便利な条件分岐の構文が用意されている。その基本的な使い方を解説。
9. while修飾子/until修飾子/while文/until文 ― ちょっと便利な繰り返し処理の構文とは?(1)
Rubyに用意されている繰り返し処理構文のうち、while文/until文の基本的な使い方と落とし穴を解説。また、while/until「修飾子」を使った簡潔な記述方法にも言及する。
10. for文 ― ちょっと便利な繰り返し処理の構文とは?(2)
Rubyに用意されている繰り返し処理の構文のうち、for文の基本的な使い方と配列と組み合わせた利用例を解説。範囲や配列を利用して一定の回数だけ繰り返して文を実行する方法や、配列全体を処理する方法を紹介する。