Crystal 有一种类型叫做Nil,它只能有一个值:nil。
它用来表示值的缺失,类似于其他语言中的null或None。
许多方法都可能返回 Nil 值,例如String#[]?,当索引越界时它会返回nil。
"foo"[10]? # => nil
Crystal 有所谓的空引用检查,这意味着默认情况下所有类型都不能为 nil。
也就是说,除非你显式地把变量声明为Nil类型,否则不能把nil赋给它。
反过来,这意味着编译器会自动检查空引用。
处理nil值有几种办法。
nil和false一样,都是假值。
这意味着,在语句以及其他需要真值或假值的地方,它都会被当作false来处理。
if nil
puts "nil is truthy"
else
puts "nil is falsey"
end
# => nil is falsey
这意味着,如果一个可为 nil 的变量的值是nil,就不会进入真值分支。
foo = "boo"[2]? # It is possible that foo is nil
if foo
p foo.class # => Char
end
Crystal 有一个方法可以用来检查某个值是否为nil。
它叫做nil?,所有对象都可以使用。
foo = "boo"[2]?
if foo.nil?
puts "foo is nil"
else
puts "foo is not nil"
end
如果只是把这个值用在if语句里,情况会有些不同:在上面的例子里,false和nil都会被当作假值。
而在这里,只有nil会被当作假值,因为如果它是false,那它就不是nil,因此会是真值。
处理nil值最简单的办法,就是从一开始就确保它们不会变成nil。
or 运算符(||)常用于处理Bools,但只要理解正确,它也可以用来处理nil值。
or 运算符会检查第一个值是否为真值,如果不是,就使用第二个值。
这样,如果值是nil,它就是假值,于是会使用第二个值。
"foo"[10]? || "bar" # => "bar"
陛下将在卡尔马联盟的首都哥本哈根举办一场晚宴。 这是全年最盛大的宴会,所有贵族都在受邀之列。 但全国各地都在流传谣言,说有人密谋毒害陛下。
陛下请你这位皇家验毒师查明,是否有食物或饮料被下了毒。 陛下计划只供应Mushroom pasties作为食物,但饮料则多种多样。
如果食物不是陛下点的,就极有可能被下了毒。如果食物不是陛下点的,就应该扔掉。
实现check_food?方法,它接受实参food,其中是以String表示的食物名称。
如果食物是Mushroom pasties,方法应返回该食物;否则应返回nil。
CastleDinner.check_food?("Mushroom pasties")
# => "Mushroom pasties"
CastleDinner.check_food?("Bread")
# => nil
饮料有可能被下了毒,但判断起来要稍微困难一些。
如果饮料名称中不包含字母i,就说明它被下了毒,大小写不限。
如果饮料被下了毒,就应该扔掉。
实现check_drink?方法,它接受实参drink,其中是以String表示的饮料名称。
如果饮料没有被下毒,方法应返回该饮料,否则应返回nil。
CastleDinner.check_drink?("Apple juice")
# => "Apple juice"
CastleDinner.check_drink?("Tea")
# => nil
陛下不希望让宾客担心食物里有毒。 因此,如果饮料被下了毒,就应该换成一款新的饮料,也就是Apple juice。
实现replace_drink方法,它接受实参drink,其中是以String表示的饮料名称。
如果饮料没有被下毒,方法应返回该饮料,否则应返回"Apple juice"。
CastleDinner.replace_drink("Orange juice")
# => "Orange juice"
CastleDinner.replace_drink("Tea")
# => "Apple juice"