Oddly Ruby behavior
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]
开发者_JS百科 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 args
in your eval
method, which gets initialized to nil
because it's on the LHS of an assignment. Then the ternary evaluates to false because args
is not an array and makes an array of the current value, which is still nil
. If args
would be an instance variable (@args
), things would work the way you expect. In other words, while inheriting from the Struct
will give you args
and args=
methods, it won't give you an @args
instance variable.
精彩评论