ループとは、与えられた条件に基づいてコードを繰り返し実行できる制御構造です。
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です。ループの最初の部分ではInt32にもStringにもなりうるからです。変数aがInt32 | Stringという型になるのは、ループの最初の部分だけです。ループが始まるときにはInt32を保持し、2回目の繰り返しではStringを保持するからです。この複数の型を持つ仕組みについては、後で詳しく説明します。しかし、ループの2番目の部分ではStringしか保持しないことが確実なので、ループの2番目の部分では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
whileを式として使うwhileは式として使えます。つまり、変数の値として使えます。返される値は、breakキーワードで与えた値です。ループ内の最後の式の値は返しません。
a = while true
break 1
end
p a
# => 1
i = 0
a = while i == 0
i += 1
1
end
p a
# => nil