I need to check if a variable is an array, and if not convert it into one before proceed with further processing. So, my code looks like this:
class Test < Struct.new(:args)
def eval
p "1. #{args}"
args = (args.instance_of? Array) ? args : [args]
p "2. #{args}" # woah! [nil]?
# ...other things, with "args" being an array for sure..or not?!?
end
end
I am quite new to ruby, so perhaps this is not very idiomatic, but to me looks like this code should at least work. Instead, the second time I print the args variable, it is [nil].
Notice that if I change the method eval slightly:
def eval
p "1. #{args}"
a = args
args = (a.instance_of? Array) ? a : [a]
p "2. #{args}"
end
everything works as expected. So, is there something very specific to the Struct class that I don't get it, or something fishy is going on here? (using ruby 1.9.3-dev on macosx, using rvm)
Actually there's a Ruby idiom for what you are trying to do:
[*args].*in this context is called the splat operator:http://raflabs.com/blogs/silence-is-foo/2010/08/07/ruby-idioms-what-is-the-splatunary-operator-useful-for/
If you get passed an array, splat will "flatten" the array into the new one, if you pass a single argument, it will become a one element array.
For the odd behavior: it looks to me like you create a local variable
argsin yourevalmethod, which gets initialized tonilbecause it's on the LHS of an assignment. Then the ternary evaluates to false becauseargsis not an array and makes an array of the current value, which is stillnil. Ifargswould be an instance variable (@args), things would work the way you expect. In other words, while inheriting from theStructwill give youargsandargs=methods, it won't give you an@argsinstance variable.