如何在 "if" 语句 [Crystal] 中使用联合
How to use union in "if" statement [Crystal]
以下代码运行良好并打印“5.0”
$x : Float64
$y : Float64
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y
现在,我更改代码以支持 "nil"。
$x : Float64?
$y : Float64?
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y if !$x.nil? && !$y.nil?
但是此代码报告以下错误消息。
no overload matches 'Float64#+' with type (Float64 | Nil)
Overloads are:
- Float64#+(other : Int8)
- Float64#+(other : Int16)
- Float64#+(other : Int32)
- Float64#+(other : Int64)
- Float64#+(other : UInt8)
- Float64#+(other : UInt16)
- Float64#+(other : UInt32)
- Float64#+(other : UInt64)
- Float64#+(other : Float32)
- Float64#+(other : Float64)
- Number#+()
Couldn't find overloads for these types:
- Float64#+(Nil)
puts $x + $y if !$x.nil? && !$y.nil?
如果 $x 或 $y 为 nil,我想停止调用方法“#+()”
如果都是Float64,则打印计算结果。
这种情况的最佳做法是什么?
在上面的代码中,我简化了这道题的代码。
结果题意不由自主的变了。。
其实我想问下面的代码。
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
puts @a + @b
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
这段代码,报如下错误。
instantiating 'Xyz#do_calc()'
x.do_calc
^~~~~~~
in ./a.cr:15: no overload matches 'Float64#+' with type (Float64 | Nil)
Overloads are:
- Float64#+(other : Int8)
- Float64#+(other : Int16)
- Float64#+(other : Int32)
- Float64#+(other : Int64)
- Float64#+(other : UInt8)
- Float64#+(other : UInt16)
- Float64#+(other : UInt32)
- Float64#+(other : UInt64)
- Float64#+(other : Float32)
- Float64#+(other : Float64)
- Number#+()
Couldn't find overloads for these types:
- Float64#+(Nil)
puts @a + @b
如何避免这个错误?
一定要阅读有关 if 的文档,并检查是否为 nil:https://crystal-lang.org/docs/syntax_and_semantics/if_var.html and https://crystal-lang.org/docs/syntax_and_semantics/if_var_nil.html
这仅适用于局部变量,因此您需要先将值分配给局部变量。
附带说明,从 Crystal 0.19.0 开始,全局变量不再存在于语言中。
我认为这是因为编译无法推断 if
子句中的类型,它不像动态类型语言。如果 @a
类型是 Nil
怎么办? Nil
类型没有 +
运算符。因此,您明确声明 @a
和 @b
是 Float64
。
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
puts @a.as(Float64) + @b.as(Float64)
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
或使用 #try
派生自 Object
抽象 class(Float 和 Nil 派生它)
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
@a.try do |a|
@b.try do |b|
puts a + b
end
end
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
最佳实践
由你决定。对我来说,这取决于上下文。我认为使用 #try
更好,因为它更明确,它解释了变量可能是 nil
类型。但是在这种情况下使用 #try
非常冗长,所以我会选择第一个解决方案。
以下代码运行良好并打印“5.0”
$x : Float64
$y : Float64
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y
现在,我更改代码以支持 "nil"。
$x : Float64?
$y : Float64?
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y if !$x.nil? && !$y.nil?
但是此代码报告以下错误消息。
no overload matches 'Float64#+' with type (Float64 | Nil) Overloads are: - Float64#+(other : Int8) - Float64#+(other : Int16) - Float64#+(other : Int32) - Float64#+(other : Int64) - Float64#+(other : UInt8) - Float64#+(other : UInt16) - Float64#+(other : UInt32) - Float64#+(other : UInt64) - Float64#+(other : Float32) - Float64#+(other : Float64) - Number#+() Couldn't find overloads for these types: - Float64#+(Nil) puts $x + $y if !$x.nil? && !$y.nil?
如果 $x 或 $y 为 nil,我想停止调用方法“#+()” 如果都是Float64,则打印计算结果。
这种情况的最佳做法是什么?
在上面的代码中,我简化了这道题的代码。 结果题意不由自主的变了。。 其实我想问下面的代码。
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
puts @a + @b
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
这段代码,报如下错误。
instantiating 'Xyz#do_calc()' x.do_calc ^~~~~~~ in ./a.cr:15: no overload matches 'Float64#+' with type (Float64 | Nil) Overloads are: - Float64#+(other : Int8) - Float64#+(other : Int16) - Float64#+(other : Int32) - Float64#+(other : Int64) - Float64#+(other : UInt8) - Float64#+(other : UInt16) - Float64#+(other : UInt32) - Float64#+(other : UInt64) - Float64#+(other : Float32) - Float64#+(other : Float64) - Number#+() Couldn't find overloads for these types: - Float64#+(Nil) puts @a + @b
如何避免这个错误?
一定要阅读有关 if 的文档,并检查是否为 nil:https://crystal-lang.org/docs/syntax_and_semantics/if_var.html and https://crystal-lang.org/docs/syntax_and_semantics/if_var_nil.html
这仅适用于局部变量,因此您需要先将值分配给局部变量。
附带说明,从 Crystal 0.19.0 开始,全局变量不再存在于语言中。
我认为这是因为编译无法推断 if
子句中的类型,它不像动态类型语言。如果 @a
类型是 Nil
怎么办? Nil
类型没有 +
运算符。因此,您明确声明 @a
和 @b
是 Float64
。
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
puts @a.as(Float64) + @b.as(Float64)
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
或使用 #try
派生自 Object
抽象 class(Float 和 Nil 派生它)
class Xyz
property a, b
@a : Float64?
@b : Float64?
def initialize
@a = nil
@b = nil
end
def do_calc
if !@a.nil? && !@b.nil?
@a.try do |a|
@b.try do |b|
puts a + b
end
end
else
puts "We can't calculate because '@a or @b has nil."
end
end
end
x = Xyz.new
x.a = 3.0_f64
x.b = 2.0_f64
x.do_calc
最佳实践
由你决定。对我来说,这取决于上下文。我认为使用 #try
更好,因为它更明确,它解释了变量可能是 nil
类型。但是在这种情况下使用 #try
非常冗长,所以我会选择第一个解决方案。