Crystalには制御式と呼ばれるものがあります。これはプログラムの実行の流れを制御するためのもので、真とみなされる値か偽とみなされる値をとります。 真とみなされる値や偽とみなされる値を作るための演算子もあり、これらは等価演算子と比較演算子と呼ばれます。
どのコードが実行され、どれが実行されないかを制御する制御式は、主に2つあります。 言い換えると、どの分岐が実行されるかを決めるものです。
それがifとunless式です。
比較演算子は値を比較し、trueかfalseを返すために使います。
これらの演算子で比較するには、同じ型の値が2つ必要です。
値の型が同じでない場合、コンパイラーがエラーを出します。
以下は比較演算子の一覧と、trueになる例です。
| メソッド | 説明 | 例 |
|---|---|---|
| < | より小さい | 4 < 5 |
| <= | 以下 | 4 <= 4 |
| > | より大きい | 3 > 1 |
| >= | 以上 | 2 >= 2 |
等価演算子は比較演算子と似ていますが、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,`と組み合わせて使うこともできますが、読みにくくなるためおすすめしません。
代わりに、`if !condition`を`else`分岐と組み合わせて使うことをおすすめします。
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には三項演算子があり、これは1行で書ける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
この演習では、原子炉の簡単な制御システムを作ってみましょう。
原子炉が出力を生み出すには、_臨界_の状態にある必要があります。 原子炉が臨界に満たない状態になると、損傷する可能性があります。 逆に臨界を超えた状態になると、過負荷になってメルトダウンを引き起こすことがあります。 ここでは、メルトダウンの可能性を抑え、原子炉の状態を正しく管理することを目指します。
以下の3つのタスクは、いずれも理想的な原子炉の状態を保つためのコードを書くことに関係しています。
制御システムが最初にすべきことは、原子炉が臨界のバランスを保っているかどうかを確認することです。 原子炉は、次の条件を満たすとき、臨界であるといいます。
ケルビンで測ったtemperatureとneutrons_emittedを仮引数に取るメソッドReactor.criticality_balanced?を実装してください。臨界の条件を満たしていればtrue、満たしていなければfalseを返します。
Reactor.criticality_balanced?(750, 600)
# => true
原子炉が出力を生み出し始めたら、その効率を求める必要があります。 効率は4つの区分に分けられます。
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の3つの仮引数を取るメソッドReactor.reactor_efficiencyを実装してください。
この関数は、原子炉の効率区分として"green"、"orange"、"red"、"black"のいずれかを返します。
Reactor.reactor_efficiency(200,50,15000)
# => "orange"
最後のタスクでは、過負荷とメルトダウンを防ぐフェイルセーフ機構を作ります。 この機構は、原子炉が理想的な臨界のしきい値より低いか、等しいか、高いかを判定します。 そして、原子炉に制御棒を挿し込む(または引き抜く)ことで、臨界を上げたり、下げたり、止めたりできます。
Reactor.fail_safe()というメソッドを実装してください。このメソッドは、ケルビンで測ったtemperature、neutrons_produced_per_second、thresholdの3つの仮引数を取り、原子炉の状態コードを出力します。
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"