Search code examples
crystal-lang

How to use union in "if" statement [Crystal]


Following code works well and print "5.0"

$x : Float64
$y : Float64
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y

Now, I change the code to support "nil".

$x : Float64?
$y : Float64?
$x = 3.0_f64
$y = 2.0_f64
puts $x + $y if !$x.nil? && !$y.nil?

However this code reports the following error message.

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?

I would like to stop the call of method "#+()" if $x or $y is nil and print the calculated result if both are Float64.

What is the best practice for this situation?


In above code, I simplified the code for this question. In the result, the meaning of question was changed involuntarily.. I wanted to ask following code actually.

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

This code, reports following error.

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

How can I avoid this error?


Solution

  • Be sure to read the docs about if, and checking for 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

    This only applies to local variables, so you'll need to assign the values to local variables first.

    As a side note, global variables don't exist anymore in the language as of Crystal 0.19.0.