user1934428
user1934428

Reputation: 22291

Calculating a map of instance variables

My module method should return a Hash, where the keys are symbols denoting the instance variables of self and the Hash values are their respective values. I came up with the following solution:

module M

  def self.set
      @foo = 5
  end

  def self.ivar_map
    Hash[instance_variables.map{|iv| [iv, instance_variable_get(iv)]}]
  end

end

M.set
M.ivar_map # => {:@foo=>5}

This works of course, but I wonder whether there isn't a simpler way to achieve the same result. After all, Ruby somehow has to maintain such a symbol table already, mapping the variables to their content.

Upvotes: 0

Views: 228

Answers (1)

Jörg W Mittag
Jörg W Mittag

Reputation: 369536

This works of course, but I wonder whether there isn't a simpler way to achieve the same result.

There are some slight simplifications that you could do:

module M
  def self.ivar_map
    instance_variables.zip(instance_variables.map(&method(:instance_variable_get))).to_h
  end
end

or with the experimental (and removed again in 2.7.0-preview3) method reference operator:

module M
  def self.ivar_map
    instance_variables.zip(instance_variables.map(&self.:instance_variable_get)).to_h
  end
end

After all, Ruby somehow has to maintain such a symbol table already, mapping the variables to their content.

Actually, that is not true. Several Ruby Implementations (including YARV, the most widely-used one) optimize instance variables to some extent. E.g. I believe YARV stores up to three instance variables in the object header directly, without using an instance variable table.

And YARV is on the more simple side when it comes to optimizations. Other implementations like Rubinius, JRuby, TruffleRuby, and RubyOMR perform much more sophisticated optimizations.

Upvotes: 2

Related Questions