Reputation: 878
I've only been learning the deep parts of Ruby for a few months so apologies if this is a bit of a dumb question. I'm attempting to recursively iterate through an Array that may contain nested Arrays and as such I need to check the type of the current element. I have the following code as a small test:
arr = [ 1..2, [3..4, [5..6]], [7..8, [9..10]] ]
arr.each do |node|
p node.class
p node.instance_of? Array
end
When I run it, I get the following output:
Range
false
Array
false
Array
false
I expected the last two to return True, given I have an Array containing a Range and two nested Arrays.
What's even weirder, is if I write the following:
node.class.name == "Array"
It returns True, as it should.
What's happening here?
Ruby Version: MRI 1.9.3-p194
Note: I eventually realised that this was occurring due to the way I namespace my code using modules to avoid code-collision, like so, but also verify object identity in a naughty way:
module MyProg
class MyClass
attr_reader :my_array
def initialize(size)
@my_array = Array.new(size)
end
end
end
MyProg::MyClass.new
Doing this isolates your code but has the downfall of causing all class lookups to be resolved starting from under your namespace. This means that in the above example, my_array.class
would actually resolve to MyProg::Array
instead of the global Array class.
If you namespace like this and you still want to use this method, you can remedy it by using the double-colon global identifier before the class to force Ruby to begin lookup from the global namespace:
arr.is_a? ::Array
arr.is_a? ::String
Given Ruby's Duck Typing abilities however (and for better code maintenance later on), you should really be testing the behaviour of the object as-per Peter's suggestion below. As such I'm marking his answer as correct for some excellent help given to a learner!
Upvotes: 4
Views: 2233
Reputation: 132307
I wrote another answer, but one major question is - why are you doing this? Why not, instead, just call flatten
on the array so you just get the entries? Or, check for the behavior of the objects instead. You might need to give more detail about what you require.
Upvotes: 3
Reputation: 93
I ran your code and got these results.
Range
false
Array
true
Array
true
I'm running ruby 1.9.3p125
Upvotes: 1