DEV Community

Cover image for TIL Tuples vs Arrays in Crystal
Mario
Mario

Posted on

TIL Tuples vs Arrays in Crystal

Today I played around with Crystal... the programming language (πŸ₯ ba-dum-tss).

Coming from Ruby, Crystal isn't a mystery in many cases, but in the end, I don't know much about it at all.

However, I learned something about Tuples and Arrays today.


It starts simple with a class that takes a String as an argument.

class TupleVsArray
  def initialize(@text : String)
    puts "Text: #{@text}"
  end
end
Enter fullscreen mode Exit fullscreen mode

Now let's decomposit an array into two variables, and then pass the first variable, foo, into the class:

foo, bar = ["foo", "bar"]
TupleVsArray.new(foo)     # Text: foo
Enter fullscreen mode Exit fullscreen mode

This works fine.
All elements in the array are of type String.
It compiles, it runs!


Let's change the second element in the array into a Symbol:

foo, bar = ["foo", :bar]
TupleVsArray.new(foo)
Enter fullscreen mode Exit fullscreen mode

This fails during compiling with this error:

Error: no overload matches 'TupleVsArray.new' with type (String | Symbol)
Enter fullscreen mode Exit fullscreen mode

To me, having little to 0 experience with type checking, this is fascinating... and confusing, because foo is allegedly never going to be a Symbol. Allegedly...

Then I realized that the array could be changed in the meantime, for example:

row = ["foo", :bar]
row[0] = :foo
foo, bar = row
TupleVsArray.new(foo)

# Error: no overload matches 'TupleVsArray.new' with type (String | Symbol)
Enter fullscreen mode Exit fullscreen mode

This time, the error makes absolutely sense.


Then I also learned, that in Crystal we cannot change an array's element to an not-yet-existing type:

row = ["foo", :bar]
row[0] = 42
Error: no overload matches '=' with types Int32, Int32
Enter fullscreen mode Exit fullscreen mode

If we want to change any element in row, we must only use String or Symbol.


So, in order to resolve the original problem, we need to use a Tuple, which is a

[...] fixed-size, immutable, stack-allocated sequence of values of possibly different types.

foo, bar = {"foo", :bar}
TupleVsArray.new(foo)     # Text: foo
Enter fullscreen mode Exit fullscreen mode

Alright, got it. 😊

(Photo by Cristofer Jeschke on Unsplash)

Top comments (0)