arraysinitializationcrystal-lang

Creating an two dimensional array in Crystal


What is a Crystal equivalent of a Ruby 2d Array accessed with indexes like:

rooms = Array.new(SIZE) { Array.new(SIZE) }
rooms[0][0] = :element

I have tried to initialize a 2d Array in Crystal in a class:

class Map
  @rooms : Array(Array(String))

  def initialize
    @rooms[0][0] = 'Test'
  end
end

But I get prompted to initialize @rooms directly in the initialize method:

Error: instance variable '@rooms' of Map was not initialized directly in all of the 'initialize' methods, rendering it nilable. Indirect initialization is not supported.

I have then tried to allocate the Array in a nested loop

@map = Array(Array(Room)).new(SIZE)
    
begin
  (0...SIZE).each do |i|
    @map[i] = Array(Room).new(SIZE)
    (0...SIZE).each do |j|
      room_type = ROOMS.sample
      puts "Create a room '#{room_type}' at cell [#{i}, #{j}]"
      @map[i][j] = Room.new(room_type)
    end
  end
rescue e : IndexError
  puts "Opps: #{e.message}"
end

However, this gives me an index of of bound error (IndexError).


Solution

  • The proper initialization in Crystal would be something like:

    Array(Array(String)).new(10) { Array(String).new(10, "") }
    

    If you want to start out with nil's as in your Ruby example then you need to make the type nilable:

    Array(Array(String?)).new(10) { Array(String?).new(10, nil) }