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 语句使用。
如果 if 分支或 unless 分支没有执行,就会执行 else 语句。
尽管 `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
elsif 语句可以配合 if 语句使用。
如果 if 分支没有执行,并且 elsif 语句的条件为真值,就会执行 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
在这个练习中,我们将为一个核反应堆开发一套简单的控制系统。
反应堆要产生功率,就必须处于临界状态。 如果反应堆的状态低于临界,它就可能受损。 如果反应堆的状态超过临界,它就可能过载并导致熔毁。 我们要降低熔毁的可能性,并正确地管理反应堆状态。
下面三个任务都与编写代码维护理想反应堆状态有关。
控制系统要做的第一件事,是检查反应堆是否处于临界平衡状态。 如果反应堆满足以下条件,就称它是临界的:
实现方法 Reactor.criticality_balanced?,它接收以开尔文为单位的 temperature和 neutrons_emitted 作为形参,如果满足临界条件就返回 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。
请注意,百分比值通常不是整数,所以要确保正确使用 < 和 <= 比较。
实现方法 Reactor.reactor_efficiency,它有三个形参:voltage、current和 theoretical_max_power。
这个方法应返回反应堆的效率区间:"green"、"orange"、"red" 或 "black"。
Reactor.reactor_efficiency(200,50,15000)
# => "orange"
你的最后一个任务是创建一个故障安全机制,以避免过载和熔毁。 这个机制将判断反应堆低于、等于还是高于理想临界阈值。 之后就可以通过向反应堆中插入(或取出)控制棒来提升、降低或停止临界状态。
实现方法 Reactor.fail_safe(),它接收 3 个形参:以开尔文为单位的 temperature、neutrons_produced_per_second和 threshold,并输出反应堆的状态码。
如果 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"