コンテンツへスキップ

while

while は、その条件がである限り、その本体を実行します。

while some_condition
  do_this
end

条件は最初にテストされ、であれば本体が実行されます。つまり、本体は決して実行されない可能性があります。

if と同様に、while の条件が変数の場合、本体内ではその変数が nil ではないことが保証されます。条件が var.is_a?(Type) テストの場合、本体内では varType 型であることが保証されます。また、条件が 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