while¶
while
は、その条件が真である限り、その本体を実行します。
while some_condition
do_this
end
条件は最初にテストされ、真であれば本体が実行されます。つまり、本体は決して実行されない可能性があります。
if
と同様に、while
の条件が変数の場合、本体内ではその変数が nil
ではないことが保証されます。条件が var.is_a?(Type)
テストの場合、本体内では var
が Type
型であることが保証されます。また、条件が var.responds_to?(:method)
の場合、var
はそのメソッドに応答する型であることが保証されます。
while
の後の変数の型は、while
の前の型と、while
の本体を抜ける前の型に依存します。
a = 1
while some_condition
# a : Int32 | String
a = "hello"
# a : String
a.size
end
# a : Int32 | String
ループの最後に条件を確認する¶
本体を少なくとも一度実行してから中断条件を確認する必要がある場合は、これを行うことができます。
while true
do_something
break if some_condition
end
または、標準ライブラリにある loop
を使用します。
loop do
do_something
break if some_condition
end
式として¶
while
の値は、while
本体から抜ける break
式の値です。
a = 0
x = while a < 5
a += 1
break "four" if a == 4
break "three" if a == 3
end
x # => "three"
while
ループが正常に終了した場合(条件が偽になった場合)、値は nil
です。
x = while 1 > 2
break 3
end
x # => nil
引数のない break
式も nil
を返します。
x = while 2 > 1
break
end
x # => nil
複数の引数を持つ break
式は、Tuple
インスタンスにパックされます。
x = while 2 > 1
break 3, 4
end
x # => {3, 4}
typeof(x) # => Tuple(Int32, Int32)
while
の型は、本体内のすべての break
式の型の和集合と、条件が失敗する可能性があるため Nil
の和集合です。
x = while 1 > 2
if rand < 0.5
break 3
else
break '4'
end
end
typeof(x) # => (Char | Int32 | Nil)
ただし、条件が正確に true
リテラルの場合、その効果は戻り値と戻り値の型から除外されます。
x = while true
break 1
end
x # => 1
typeof(x) # => Int32
特に、break
がない while true
式は、同じスコープ内でループを終了できないため、NoReturn
型になります。
x = while true
puts "yes"
end
x # unreachable
typeof(x) # => NoReturn