ループとは、与えられた条件に基づいてコードを繰り返し実行できるようにする制御構造です。
whileループwhileループは、与えられた条件に基づいてコードを繰り返し実行できるようにする制御構造です。
whileループ内のコードは、条件が真として評価される限り実行され続けます。
whileループは、繰り返しの回数が事前にわからない場合によく使われますが、ループが必要なあらゆる場面で使うことができます。
条件はループ内のコードが実行される前に評価されます。つまり、条件が偽であれば、ループ内のコードは一度も実行されません。
i = 0
while i < 3
puts i
i += 1
end
# Output:
# 0
# 1
# 2
文字列を繰り返し処理したいときは、文字列の長さの分だけループを回すことができます。
str = "Hello"
i = 0
while i < str.size
puts str[i]
i += 1
end
# Output:
# H
# e
# l
# l
# o
untilループuntilループはwhileループと同じように動作しますが、ループ内のコードは条件が真として評価されるまで実行され続ける点が異なります。
これはifとunlessの違いと同じです。
i = 0
until i == 3
puts i
i += 1
end
whileループでよくある間違いは、決して終わらない「無限ループ」に入ってしまうことです。
無限ループは、条件が_決して_真または偽として評価されないことが原因で起こることがあります。
これは多くの場合、プログラマーのミスによるものです。たとえば、ループ変数をインクリメントし忘れるなどです。
しかし、プログラムのロジックを実装するうえで、無限ループがもっともわかりやすい方法であることもあります。
あるいは、永遠にループし続けることが不可欠な場合もあります。たとえば、HTTPサーバーは接続を待ち受け、それを処理し、そして次の接続を待ちます。
breakbreakキーワードを使うと、ループを途中で抜けることができます。
特定の条件でループを途中で抜けたいときに便利です。
i = 0
while i <= 3
puts i
i += 1
if i == 2
break
end
end
# Output:
# 0
# 1
nextnextキーワードを使うと、ループの次の繰り返しにスキップできます。
ループの特定の繰り返しをスキップしたいときに便利です。
i = 0
while i <= 3
i += 1
if i == 2
next
end
puts i
end
# Output:
# 1
# 3
ループの中では、変数の型が変わることがあります。
次の例では、ループの前半でaがInt32にもStringにもなりうるため、aの型はInt32 | Stringです。
変数aが型Int32 | Stringを持つのはループの前半だけです。ループが始まったときはInt32を保持し、2回目の繰り返しではStringを保持するからです。
この複数の型を扱う仕組みについては、後ほど詳しく説明します。
ただし、ループの後半ではStringしか保持されないことが確実なので、ループの後半におけるaの型はStringです。
実行時には、Int32とStringを同時に保持することはありません。
i = 0
a = 4
while i < 3
p typeof(a)
# => Int32 | String
a = "4"
p typeof(a)
# => String
i += 1
end
Crystalでは、メソッドの最後の式がその値を返します。
しかし、最後の式より前に値を返したいこともあります。
そのようなときはreturnキーワードを使います。returnは、直後の式の値を返します。
returnキーワードより後に書かれたコードは実行されません。
def speed_limit(road_number)
if road_number == 1
return 50
puts "This will not be executed"
elsif road_number == 2
return 80
puts "This will not be executed"
end
100
end
p speed_limit(1) # => 50
p speed_limit(2) # => 80
p speed_limit(3) # => 100
メソッドの最後の式が返すべき値である場合は、returnキーワードは省略します。
この演習では、貯蓄口座を扱います。 貯蓄口座の残高は、毎年、その利率に基づいて更新されます。 銀行が適用する利率は、口座に入っている金額(残高)によって決まります。
1000ドル未満の場合は0.5%です。1000ドル以上5000ドル未満の場合は1.621%です。5000ドル以上の場合は2.475%です。4つのタスクがあり、それぞれで残高と利率を扱います。
残高を引数に取るSavingsAccount.interest_rate()メソッドを実装します。
このメソッドは、与えられた残高に対する利率を返すようにします。
SavingsAccount.interest_rate(200.75)
# => 0.5
残高を引数に取るSavingsAccount.interest()メソッドを実装します。
このメソッドは、与えられた残高に対する利息を返すようにします。
SavingsAccount.interest(200.75)
# => 1.00375
残高を引数に取るSavingsAccount.annual_balance_update()メソッドを実装します。
このメソッドは、1年後の残高を返すようにします。
SavingsAccount.annual_balance_update(200.75)
# => 201.75375
残高と目標残高を引数に取るSavingsAccount.years_before_desired_balance()メソッドを実装します。
このメソッドは、目標残高に達するまでにかかる年数を返すようにします。
balance = 200.75
target_balance = 214.88
SavingsAccount.years_before_desired_balance(balance, target_balance)
# => 14
単利を元本残高に適用するときは、残高に利率を掛け、その積が利息額になります。
一方、複利は利息を定期的に適用することで計算します。 適用のたびに利息額を計算して元本残高に加算するので、その後の利息計算は、より大きな元本残高に対して行われることになります。