루프는 주어진 조건에 따라 코드를 반복해서 실행할 수 있게 해 주는 제어 구조예요.
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 서버는 들어오는 연결을 기다리고, 처리한 다음, 다음 연결을 기다려요.
break 키워드를 사용하면 루프를 일찍 빠져나갈 수 있어요.
특정 조건에서 루프를 일찍 빠져나가고 싶을 때 편리해요.
i = 0
while i <= 3
puts i
i += 1
if i == 2
break
end
end
# Output:
# 0
# 1
next 키워드를 사용하면 루프의 다음 반복으로 건너뛸 수 있어요.
루프의 특정 반복을 건너뛰고 싶을 때 편리해요.
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를 담고 있고, 두 번째 반복에서는 String을 담고 있기 때문이에요.
이 여러 타입 시스템은 나중에 자세히 설명해요.
하지만 루프의 뒷부분에서는 String만 담는다는 걸 확실히 알 수 있으므로, 루프의 뒷부분에서 a의 타입은 String이에요.
실행 중에 a가 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