I already asked a related question here and the answer did fix my issue but I have a more general misunderstanding of how crystal checks types since I keep running into similar issue so if someone could help me figure this out I'd be greatful. I've tried many things that would work great with Ruby but are absolutely not working with Crystal (I know they have many differences but I'm more familiar with Ruby).
Here is a class:
class Narray(T)
getter shape
getter values
@shape : Tuple(Int32, Int32) | Nil
def initialize(values : T)
@values = values
@type = T
@shape = set_shape
end
def set_shape
if (@type == Array(Array(Int32))) || (@type == Array(Array(Float64)))
return {values.size, values[0].size} # Line causing the error
elsif (@type == Array(Int32)) || (@type == Array(Float64))
return {1, @values.size}
end
end
def is_matrix?
if @values[0].is_a?(Array(Int32)) || @values[0].is_a?(Array(Float64))
return true
else
return false
end
end
end
To define an array, I should do:
arr1 = Narray.new([1,2,3])
Which would run through set_shape
to retrieve the shape of the array (a tuple representing the number of rows and number of columns).
In this method, I check in the if statement if it's a 2D array or not.
However, when running the line above, I get this error:
in script.cr:16: undefined method 'size' for Int32
return {values.size, values[0].size}
Which is exactly what the first if statement should avoid. Since I'm initializing a 1D array, it shouldn't go through the .size
part.
I'm pretty sure it's a trivial explanation, and that there is something pretty basic that I didn't get but I'd like to get it instead of stumbling upon this issue all the time.
How can I check for type in Crystal since the way I'm using isn't the right way ?
I've tried using is_a?
, == Type
, using the is_matrix?
method (which works fine and does the job of determining if it's 2D or 1D but still runs through the wrong part).
EDIT: according to the first answer, I've changed the set_shape
method:
def set_shape
if (@values.is_a? Array(Array(Int32))) || (@values.is_a? Array(Array(Float64)))
return {values.size, values[0].size}
elsif (@values.is_a? Array(Int32)) || (@values.is_a? Array(Float64))
return {1, @values.size}
end
end
But I still have the exact same error