case는 다른 언어에서 흔히 switch라고 부르는 제어 표현식으로, if-else와 비슷해요.
case를 사용하면 여러 개의 if-else-if 문을 이어서 쓸 수 있고, 코드가 더 읽기 쉬워지며, 강력한 구성도 가능해요.
case는 case 키워드 뒤에 선택적인 표현식을 붙여 정의해요.
그런 다음 케이스마다 when 키워드 뒤에 케이스 표현식과 비교할 표현식을 적어요.
when 키워드는 case 키워드보다 안쪽으로 들여쓰면 안 돼요.
when 키워드 뒤에는 케이스 표현식이 when 표현식과 일치할 때 실행할 코드를 적어요.
case에는 다른 케이스가 하나도 일치하지 않을 때 실행되는 선택적인 else 문도 쓸 수 있어요.
케이스 표현식을 평가한 다음 각 when 표현식과 비교해요.
비교할 때는 케이스 포섭 연산자(===)를 사용해요.
case 1
when 1
puts "One"
when 2
puts "Two"
else
puts "Other"
end
# => One
# This is the same as:
tmp = 1
if 1 === tmp
puts "One"
elsif 2 === tmp
puts "Two"
else
puts "Other"
end
===)케이스 포섭 연산자(===)는 동등 연산자(==)와는 조금 달라요.
이 연산자는 오른쪽 값이 왼쪽 값이 나타내는 집합에 속하는지 확인해요.
그래서 각 피연산자를 어느 쪽에 두는지가 중요해요.
동작 방식은 왼쪽 값의 타입에 따라 달라요. 예를 들어 Range는 오른쪽 값이 범위 안에 있는지 확인하고, Object는 오른쪽 값이 Object의 인스턴스인지 확인해요.
(1..3) == 1 # => false
(1..3) === 1 # => true
String == "foo" # => false
String === "foo" # => true
케이스에서는 하나의 when에 여러 표현식을 나열해 일치시킬 수 있고, 각 값은 쉼표로 구분해요. 표현식 중 하나라도 일치하면 코드를 실행해요. 하나의 케이스에 가능한 값이 여러 개일 때 유용해요.
case 1
when 1, 2
puts "One or two"
else
puts "Other"
end
케이스는 값이 범위 안에 있는지도 확인할 수 있어요. 이때는 when 표현식에 범위를 적어요.
case var
when 1..3
puts "One to three"
else
puts "Other"
end
케이스 표현식이 필요 없을 때는 생략할 수 있어요. 이렇게 하면 각 when 표현식이 참으로 평가되는지 따지게 되고, if-else-if 문처럼 동작해요.
case
when 1 == 1
puts "One is equal to one"
when 1 > 2
puts "One is greater than two"
else
puts "Other"
end
Crystal에서는 한 줄짜리 케이스 문도 쓸 수 있어요.
간단한 한 줄 문장일 때 사용하면 좋아요.
한 줄 when 문은 when <expression> then <statement>.처럼 쓰고, else 문에 쓸 때는 else <statement>처럼 써요.
case var
when 1 then puts "One"
when 2 then puts "Two"
else puts "Other"
end
케이스는 타입과도 일치시킬 수 있어요.
이때는 is_a? 연산자로 변수의 타입을 확인해요.
예를 들어 유니언 타입에서 각 타입마다 분기를 하나씩 만들 수 있어요.
case var
when Int32
puts "Int32"
when String
puts "String"
else
puts "Other"
end
케이스는 암시적 객체를 사용할 수 있어요. 그러면 예를 들어 when 표현식을 케이스 표현식에 대한 메서드 호출로 쓸 수 있어요. 메서드가 참 같은 값을 반환하는지 거짓 같은 값을 반환하는지에 따라 케이스가 일치할지 정해져요.
case 1
when .odd?
puts "Odd"
when .even?
puts "Even"
end
케이스는 모든 경우를 다루도록 만들 수 있어요. 즉, 가능한 모든 값을 처리하도록 보장할 수 있어요.
when 대신 in 키워드를 쓴다는 점만 빼면 when 문과 비슷해요.
모든 경우를 다루는 케이스에서는 when이나 else 문을 쓸 수 없어요.
모든 경우를 다루는 케이스는 Bools, Union 타입, Enum, Tuples에 사용할 수 있어요.
뒤의 두 가지는 나중 개념에서 다뤄요.
모든 경우를 다루는 케이스는 가능한 모든 경우를 처리해야 하고, 그러지 않으면 컴파일 오류가 발생해요.
Union 타입을 모든 경우를 다루는 케이스로 처리하는 방법은 그렇지 않은 케이스와 비슷해요.
var : (Int32 | String | Bool)
case var
in Int32
puts "Int32"
in String
puts "String"
in Bool
puts "Bool"
end
Bools는 true와 false 키워드로 모든 경우를 다루는 케이스로 처리할 수 있어요.
var : Bool
case var
in true
puts "True"
in false
puts "False"
end