while

    The condition is first tested and, if truthy, the body is executed. That is, the body might never be executed.

    Similar to an if, if a while‘s condition is a variable, the variable is guaranteed to not be nil inside the body. If the condition is an var.is_a?(Type) test, var is guaranteed to be of type Type inside the body. And if the condition is a var.responds_to?(:method), var is guaranteed to be of a type that responds to that method.

    The type of a variable after a while depends on the type it had before the while and the type it had before leaving the while‘s body:

    1. a = 1
    2. while some_condition
    3. # a : Int32 | String
    4. a = "hello"
    5. # a : String
    6. a.size
    7. end
    8. # a : Int32 | String
    1. while true
    2. do_something
    3. break if some_condition

    Or use loop, found in the standard library:

    As an expression

    The value of a while is the value of the break expression that exits the while‘s body:

    1. a = 0
    2. x = while a < 5
    3. a += 1
    4. break "four" if a == 4
    5. break "three" if a == 3
    6. end
    7. x # => "three"

    If the while loop ends normally (because its condition became false), the value is nil:

    1. x = while 1 > 2
    2. break 3
    3. end
    4. x # => nil

    break expressions with multiple arguments are packed into instances:

    1. x = while 2 > 1
    2. break 3, 4
    3. x # => {3, 4}
    4. typeof(x) # => Tuple(Int32, Int32)

    The type of a while is the union of the types of all break expressions in the body, plus Nil because the condition can fail:

    1. x = while 1 > 2
    2. if rand < 0.5
    3. break 3
    4. else
    5. break '4'
    6. end
    7. end
    8. typeof(x) # => (Char | Int32 | Nil)

    However, if the condition is exactly the true literal, then its effect is excluded from the return value and return type:

    1. x = while true
    2. puts "yes"
    3. end
    4. typeof(x) # => NoReturn