制御構造
条件分岐
if
条件式を評価した結果が真である場合、then以下の式を評価します。ifの条件式が偽であれば、elsifの条件を評価します。すべてのifおよびelseifの条件式が偽であった場合、elseが評価されます。else節がなくいずれの条件も成り立たなければnilを返します。Rubyではfalseまたはnilだけが偽で、それ以外は0や空文字も含めすべて真です。
if n.zero?
puts "0です"
elsif n.even?
puts "偶数です"
elsif n.odd?
puts "奇数です"
end
if修飾子
右辺の条件が成立する場合に、左辺の式を評価してその結果を返します。条件が成立しなければnilを返します。
e.errors.messages if e.valid?
unless
unlessはifと反対で、条件式が偽のときにthen以下の式を評価します。unless式にelsifを指定することはできません。
unless n.zero?
puts "0ではありませんでした"
else
puts "0です"
end
unless修飾子
右辺の条件が成立しない時に、左辺の式を評価してその結果を返します。条件が成立すればnilを返します。
puts "0ではありませんでした" unless n.zero?
case
caseは一つの式に対する一致判定による分岐を行います。when節で指定された値と最初の式を評価した結果とを演算子===
を用いて比較して、一致する場合はwhen節の本体を評価します。
case age
when 0..2
"baby"
when 3..6
"little child"
when 13..18
"youth"
else
"adult"
end
===
メソッドのオブジェクトごとの動作
メソッドオブジェクト | 動作 |
---|---|
Range | 引数が自身の範囲内に含まれるなら真を返す |
Regexp | 引数の文字列がマッチした場合、真を返す |
Proc | 右辺を引数にして手続きオブジェクトを実行した結果を返す |
Module, Class | 引数が自身または自身のサブクラスのインスタンスであれば真を返す |
繰り返し
while
式を評価した値が真の間、本体を繰り返し実行します。breakによりwhile式の戻り地をその値にすることもできます。
ary = [0, 4, 4, 8, 16]
i = 0
while i < ary.length
print ary[i]
i += 1
end
while 修飾子
右辺の式を評価した値が真の間、左辺を繰り返し実行します。
左辺の式がbegin節である場合にはそれを最初に1回評価してから繰り返します。
send_request(data)
begin
res = get_response()
end while res == "Continue"
until
式を評価した値が真になるまで、本体を繰り返して実行します。 引数を伴ったbreakによりuntil式の戻り値をその値にすることもできます。
until修飾子
右辺の式を評価した値が真になるまで、左辺を繰り返して実行します。
左辺の式がbegin節である場合にはそれを最初に1回評価してから繰り返します。
send_request(data)
begin
res = get_response()
end until res === "OK"
for
式を評価した結果のオブジェクトの各要素に対して本体を繰り返して実行します。
for i in 5.times
p i
end
break
breakはもっとも内側のループを脱出します
以下のいずれかを指します
- while
- untile
- for
- イテレータ
i = 0
while i < 3
print i, "\n"
break
end
next
nextはもっとも内側のループの次の繰り返しにジャンプします。イテレータでは、yield呼び出しの脱出になります。nextにより抜けたyield式はnilを返します。ただし、引数を指定した場合、yield式の戻り値はその引数になります。
ARGF.each do |line|
next if line.strip.empty?
print line
end
retry
retryは、rescue節でbegin式をはじめからもう一度実行するのに使用します。retryを使うことである処理が成功するまで処理を繰り返すようなループを作ることが出来ます。
rescue節以外でretryが用いられた場合には例外、SyntaxError
が発生します。
begin
do_something
rescue StandardError => e
retry
end
例外処理
例外とは何らかの異常が発生したことを表すオブジェクトです。
例外の発生と例外クラス
プログラムの実行中にエラーが有ると例外が発生します。ある場所で例外が発生したとき、例外はコールスタックをさかのぼり、最終的にはトップレベルまで伝搬していきます。
例外クラス
- Exception : すべての例外クラスの祖先クラス
- NoMemoryError : メモリの確保に失敗すると発生
- ScriptError : スクリプトのエラーを表す外クラス
- LoadError :
Kernel.#require
やKernel.#load
が失敗した時に発生 - NotImplementedError : 現在のプラットフォームで実装されていない機能が呼び出された時に発生
- SyntaxError : ソースコードに文法エラーがあったときに発生
- LoadError :
- SecurityError : セキュリティ上の問題が起きた時に発生
- SignalException : 補足していないシグナルを受け取った時に発生
- Interrput :
SIGINT
シグナルを補足していない時にSIGINT
シグナルを受け取ると発生
- Interrput :
- StandardError : 通常のプログラムで発生する可能性が高い例外クラスを束ねるためのクラス。独自で例外クラスを作成する場合は、基本このクラスを継承することが推奨されている
- ArgumentError : 引数の数があっていないときや、数は合っていて、期待される振る舞いを持ってはいるが、期待される値では無い時に発生
- UncaughtThrowError :
Kernel.#throw
に指定したtagに対して一致するKernel.#catch
が存在しない場合に発生
- UncaughtThrowError :
- EncodingError : エンコーディング関連の例外の基底クラス
- FiberError : Fiberに関するエラーが起きると発生
- IOError : 入出力でエラーが起きると発生
- EOFError : EOFに達成した時に発生
- IndexError : 添字が範囲外の場合に発生
- KeyError :
Hash#fetch
などでkeyに対応するvalueがない場合に発生 - StopIteration : イテレーションを止める時に発生
- ClosedQueueError : close済みの
Thread::Queue
やThread::SizedQueue
に許可されていない操作を行おうとした場合に発生
- ClosedQueueError : close済みの
- KeyError :
- LocalJumpError : ある
Proc
オブジェクトの作成元スコープがすでに終了しているとき、そのProc
オブジェクト内でreturn
,break
,retry
のいずれかを実行すると発生 - Math::DomainError : 数学関数(
Math
のモジュール関数)で与えた引数が定義域に含まれていな場合に発生 - NameError : 未定義のローカル変数や定数を使用した時に発生
- NoMethodError : 定義されていないメソッドの呼び出しが行われた時に発生
- RangeError : 範囲に関する例外クラス。値が定義域から外れている時に発生
- FloatDomainError : 正負の無限大やNaN(Not a Number)を
Bignum
に変換しようとしたり、NaNとの比較を行った時に発生
- FloatDomainError : 正負の無限大やNaN(Not a Number)を
- RegexpError : 正規表現のコンパイルに失敗した時に発生
- RuntimeError : 特定の例外クラスに該当しないエラーが起こった時に発生。
Kernel.#raise
で例外クラスを指定しなかった場合もRuntimeError
が発生する- FrozenError :
Object#freeze
されたオブジェクトを変更しようとした時に発生
- FrozenError :
- SystemCallError : Rubyの実装に用いられているシステムコールまたは一部のC言語関数が失敗した時に発生
- ThreadError :
Thread
関連のエラーが起きたときに発生 - TypeError : メソッドの引数に期待される型ではないオブジェクトや、期待される振る舞いを持たないオブジェクトが渡された時に発生
- ZeroDivisionError : 整数に対し整数の0で除算を行ったときに発生
- ArgumentError : 引数の数があっていないときや、数は合っていて、期待される振る舞いを持ってはいるが、期待される値では無い時に発生
- SystemExit : Rubyインタプリタを終了させるときに発生
- SystemStackError : システムスタックがあふれた時に発生
raise
例外を発生させます。raiseの第一引数に文字列を指定した場合は、それを例外のメッセージとしてRuntimeError
を発生させます。
raise "Error #{e}"
raise StandardError, "error"
begin
本体の実行中に例外が発生した場合、rescue節が与えられていれば、例外を補足できます。発生した例外と一致するrescue節が存在する場合は、rescue節の本体が実行されます。変数を指定すると発生した例外が格納されます
begin
raise "error"
rescue StandardError => e
p e
p $!
end
- 例外クラスを複数指定
begin
do_process
rescue ArgumentError, NameError => e
puts e
end
- 発生した例外クラスによってrescueを分ける
begin
do_process
rescue ArgumentError => e
puts e
rescue NameError => e
raise e
end
ensure
例外の有無に関わらず、最後にかならず実行したい処理はensure節に記述します。
begin
file = File.open("input.txt")
do_process file
rescue IOError => e
puts e
ensure
file.close if file
end
elseを使うと、例外が発生しなかった場合だけ行う処理を記述することもできます。
begin
file = File.open("input.txt")
do_process file
rescue IOError => e
puts e
else
puts "success file process"
ensure
file.close if file
end
例外処理の戻り値
begin節、rescue節、またはelse節で最後に評価された式の値が戻り値になります
result = begin
"success"
rescue StandardError => e
puts e
"failed"
ensure
puts "this is not return value" # 実行されるが戻り値とはならない
end
メソッドやクラス/モジュール定義で例外を補足する
resucue節、ensure節、else節はbegin以外にも組み合わせて使用することが出来ます。これらはメソッド定義式、クラス定義式、モジュール定義式に記述することが出来ます。
# メソッド呼び出し時に発生した例外を補足する
def do_process
"hoge"
rescue StandardError => e
puts e
end
# クラス定義時に発生したエラーを補足する
class Klass
def initialize
super
end
rescue StandardError => e
puts e
end