if

if (조건문)

프로그램에서 조건에 따라 실행 흐름을 나누는 가장 기본적인 문장이 바로 if예요. Crystal의 if는 주어진 조건이 참(truthy)일 때 해당 분기를 실행하고, 그렇지 않으면 else 분기가 있으면 그것을 실행해요. 다른 언어와 비슷하지만, 타입 추론과 값 반환에서 Crystal만의 특징이 있어요.

출처: Crystal 공식 문서 - if

본문

if는 주어진 조건이 _truthy_할 때 해당 분기를 평가해요. 조건이 참이 아니면, else 분기가 있다면 그 분기를 평가해요.

a = 1
if a > 0
  a = 10
end
a # => 10

b = 1
if b > 2
  b = 10
else
  b = 20
end
b # => 20

if-else if의 연쇄를 만들 때는 elsif를 사용해요.

if some_condition
  do_something
elsif some_other_condition
  do_something_else
else
  do_that
end

if가 끝난 뒤에는 변수의 타입이 양쪽 분기에서 사용된 표현식들의 타입에 따라 결정돼요.

a = 1
if some_condition
  a = "hello"
else
  a = true
end
# a : String | Bool

b = 1
if some_condition
  b = "hello"
end
# b : Int32 | String

if some_condition
  c = 1
else
  c = "hello"
end
# c : Int32 | String

if some_condition
  d = 1
end
# d : Int32 | Nil

한쪽 분기에서만 변수를 선언하고 다른 쪽에서는 선언하지 않았다면, if가 끝나는 시점에는 그 변수의 타입에 Nil도 포함돼요. 실행되지 않을 수도 있으니까, 없다(nil)는 가능성을 타입에 담아두는 거예요.

if의 분기 안에서는 변수의 타입이 그 분기에서 할당된 타입이에요. 분기에서 다시 할당하지 않았다면 분기 이전의 타입을 그대로 가져요.

a = 1
if some_condition
  a = "hello"
  # a : String
  a.size
end
# a : String | Int32

즉, 변수의 타입은 마지막으로 할당된 표현식의 타입이에요. 분기 안에서 마지막 할당이 String이었다면 그 지점에서는 String으로 추론되는 거죠.

만약 어떤 분기가 return, next, break, raise처럼 if의 끝을 넘어서 절대 도달하지 못하는 경우라면, 그 타입은 if가 끝난 뒤의 타입 계산에서 제외돼요.

if some_condition
  e = 1
else
  e = "hello"
  # e : String
  return
end
# e : Int32

else 분기가 return으로 끝나기 때문에 평범하게 흐름이 이어질 때는 e = 1만 실행되는 셈이에요. 그래서 if 이후의 e 타입은 Int32가 돼요.

더 알아보기

  • if가 값을 만들어내는 성질은 As an expression 문서에서 다뤄요.
  • 조건에 따라 값을 고르는 간결한 문법은 Ternary if에서 확인할 수 있어요.