Reputation: 22291
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
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:
Array#to_h
instead of Hash::[]
.Array#zip
.Object#method
or something like the method reference operator if that is ever added to Ruby.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