Crystal에는 제어식이라는 것이 있어요. 제어식은 프로그램이 실행되는 방식을 제어하는 데 사용되고, 참 같은 값이나 거짓 같은 값을 가져요. 참 같은 값이나 거짓 같은 값을 만드는 데 쓸 수 있는 연산자들도 있는데, 이것을 동등 및 비교 연산자라고 해요.
어떤 코드가 실행되고 어떤 코드는 실행되지 않을지, 다시 말해 주어진 분기 중 어느 것이 실행될지를 제어하는 주요 제어식이 두 가지 있어요.
그 두 가지는 if와 unless 표현식이에요.
비교 연산자는 값을 비교해서 true 또는 false 값을 반환하는 데 사용해요.
이 연산자들은 비교하려면 같은 타입의 값 두 개가 필요해요.
값의 타입이 다르면 컴파일러가 오류를 발생시켜요.
다음은 비교 연산자 목록과, 이 연산자들이 true 값을 내놓는 예시예요:
| 메서드 | 설명 | 예시 |
|---|---|---|
| < | 보다 작음 | 4 < 5 |
| <= | 보다 작거나 같음 | 4 <= 4 |
| > | 보다 큼 | 3 > 1 |
| >= | 보다 크거나 같음 | 2 >= 2 |
동등 연산자는 비교 연산자와 비슷하지만, 두 값이 같은지 아닌지를 확인하는 데 사용해요.
== 연산자는 값의 타입을 포함해서 두 값이 같은지 확인해요.
값이 같으면 true를 반환하고, 그렇지 않으면 false를 반환해요.
== 연산자는 어떤 타입의 값이든 다른 어떤 타입의 값과도 비교할 수 있어요.
!=도 같은 방식으로 동작하지만, 값이 다르면 true를, 같으면 false를 반환해요.
if문if문은 주어진 조건이 참 같은 값인지 거짓 같은 값인지 확인하는 데 사용해요.
조건이 참 같은 값이면 if문 안의 코드가 실행돼요.
if문은 end 키워드로 끝나요.
if 1 == 1
puts "1 is equal to 1"
end
# => 1 is equal to 1
if 1 > 2
puts "1 is greater than 2"
end
# => no output
unless문unless문은 if문과 아주 비슷하게 동작하지만, 조건이 거짓 같은 값일 때 unless문 안의 코드를 실행해요.
unless 1 == 1
puts "1 is not equal to 1"
end
# => no output
unless 1 > 2
puts "1 is not greater than 2"
end
# => 1 is not greater than 2
else문else문은 if문과 unless문에 함께 사용할 수 있어요.
else문은 if 분기나 unless 분기가 실행되지 않았을 때 실행돼요.
`else` 분기는 `unless,`와 함께 사용할 수 있지만, 가독성을 해치기 때문에 그렇게 하는 것은 권장하지 않아요.
대신 `else` 분기와 함께 `if !condition`을 사용하는 것을 권장해요.
if 1 == 1
puts "1 is equal to 1"
else
puts "1 is not equal to 1"
end
# => 1 is equal to 1
unless 1 < 2
puts "1 is not greater than 2"
else
puts "1 is greater than 2"
end
# => 1 is greater than 2
if문elsif문은 if문과 함께 사용할 수 있어요.
elsif문은 if 분기가 실행되지 않았고 elsif문의 조건이 참 같은 값일 때 실행돼요.
elsif문은 여러 개를 이어 붙일 수 있고, 처음으로 조건이 참이 되는 분기가 실행돼요.
if문 끝에 else문을 둘 수도 있는데, 이는 앞의 조건들이 모두 참이 아니었을 때 실행돼요.
if 1 != 1
puts "1 is not equal to 1"
elsif 1 > 2
puts "1 is greater than 2"
else
puts "1 is not equal to 1 and 1 is not greater than 2"
end
# => 1 is not equal to 1 and 1 is not greater than 2
변수에 서로 다른 타입이 대입되면, 변수는 두 타입을 모두 가지게 돼요. 컴파일러는 어느 분기가 실행될지 모르기 때문이에요. 이렇게 여러 타입이 함께 대입되는 것을 유니언이라고도 하는데, 이는 뒤의 개념에서 설명해요. 다음 예시에서 확인할 수 있어요:
if 1 == 1
a = 1
else
a = "1"
end
typeof(a) # => Int32 | String
Crystal에는 한 줄짜리 if-else문인 삼항 연산자가 있어요: condition ? expression_if_truthy : expression_if_falsey
1 == 1 ? puts("1 is equal to 1") : puts("1 is not equal to 1")
# => 1 is equal to 1
이 연습 문제에서는 원자로를 위한 간단한 제어 시스템을 만들어 봐요.
원자로가 전력을 생산하려면 _임계 상태_에 있어야 해요. 원자로가 임계 상태보다 낮으면 손상될 수 있어요. 반대로 임계 상태를 넘어서면 과부하가 걸려 노심 용융으로 이어질 수 있어요. 우리는 노심 용융의 가능성을 줄이고 원자로 상태를 올바르게 관리하고자 해요.
다음 세 가지 작업은 모두 이상적인 원자로 상태를 유지하기 위한 코드를 작성하는 것과 관련이 있어요.
제어 시스템이 가장 먼저 해야 할 일은 원자로가 임계 상태에서 균형을 이루고 있는지 확인하는 거예요. 다음 조건을 만족하면 원자로가 임계 상태에 있다고 해요:
켈빈 단위로 측정한 temperature와 neutrons_emitted를 매개변수로 받아, 임계 조건이 충족되면 true를, 그렇지 않으면 false를 반환하는 Reactor.criticality_balanced? 메서드를 구현해요.
Reactor.criticality_balanced?(750, 600)
# => true
원자로가 전력을 생산하기 시작하면 그 효율을 판단해야 해요. 효율은 네 구간으로 나눌 수 있어요:
green -> 효율 80% 이상,orange -> 효율 80% 미만이지만 60% 이상,red -> 효율 60% 미만이지만 30% 이상,black -> 효율 30% 미만.백분율 값은 (generated_power/theoretical_max_power)*100으로 계산할 수 있는데, 여기서 generated_power = voltage * current예요.
백분율 값은 보통 정수가 아니므로, <와 <= 비교를 올바르게 사용해야 한다는 점에 유의해요.
voltage, current, theoretical_max_power 세 매개변수를 받는 Reactor.reactor_efficiency 메서드를 구현해요.
이 함수는 원자로의 효율 구간인 "green", "orange", "red", "black" 중 하나를 반환해야 해요.
Reactor.reactor_efficiency(200,50,15000)
# => "orange"
마지막 작업은 과부하와 노심 용융을 막기 위한 고장 안전 메커니즘을 만드는 거예요. 이 메커니즘은 원자로가 이상적인 임계값보다 낮은지, 임계값에 있는지, 아니면 그보다 높은지를 판단해요. 그런 다음 원자로에 제어봉을 삽입하거나 제거해서 임계 상태를 높이거나 낮추거나 멈출 수 있어요.
켈빈 단위로 측정한 temperature, neutrons_produced_per_second, threshold 세 매개변수를 받아 원자로의 상태 코드를 출력하는 Reactor.fail_safe() 메서드를 구현해요.
temperature * neutrons_produced_per_second가 threshold의 90%보다 작으면 "LOW" 상태 코드를 출력해서, 전력을 생산하려면 제어봉을 제거해야 한다는 것을 알려요.
temperature * neutrons_produced_per_second가 threshold의 ±10% 이내라면 원자로는 _임계 상태_에 있고 "NORMAL" 상태 코드를 출력해야 해요. 이는 원자로가 최적 상태이고 제어봉이 이상적인 위치에 있다는 것을 나타내요.
temperature * neutrons_produced_per_second가 위에 나온 범위에 들지 않으면 원자로가 노심 용융으로 가고 있는 것이므로, 원자로를 즉시 정지시키기 위해 "DANGER" 상태 코드를 전달해야 해요.
temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"
Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.