奇怪的 Ruby 行为
我需要检查变量是否是数组,如果不是,则在继续进一步处理之前将其转换为数组。所以,我的代码看起来像这样:
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
我对 ruby 很陌生,所以也许这不是很惯用,但对我来说,这段代码至少应该可以工作。相反,我第二次打印 args
变量时,它是 [nil]
。
请注意,如果我稍微更改方法 eval
:
def eval
p "1. #{args}"
a = args
args = (a.instance_of? Array) ? a : [a]
p "2. #{args}"
end
一切都会按预期工作。那么,是否有一些关于 Struct 类的非常具体的东西我不明白,或者这里发生了什么可疑的事情? (在macosx上使用ruby 1.9.3-dev,使用rvm)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
实际上,有一个 Ruby 习惯用法可以满足您想要执行的操作:
[*args]
。*
在这种情况下称为 splat 运算符:http://raflabs.com/blogs/silence-is-foo/2010/08/07/ruby-idioms-what-is-the-splatunary-operator-useful-for/
如果您传递一个数组,splat 会将数组“展平”为新数组,如果您传递单个参数,它将成为一个单元素数组。
对于奇怪的行为:在我看来,您在
eval
方法中创建了一个局部变量args
,该变量被初始化为nil
因为它处于打开状态作业的 LHS。然后,三元计算结果为 false,因为 args 不是数组,它会生成当前值的数组,该值仍然是 nil。如果args
是一个实例变量 (@args
),事情就会按照您期望的方式工作。换句话说,虽然从Struct
继承将为您提供args
和args=
方法,但它不会为您提供@ args
实例变量。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 youreval
method, which gets initialized tonil
because it's on the LHS of an assignment. Then the ternary evaluates to false becauseargs
is not an array and makes an array of the current value, which is stillnil
. Ifargs
would be an instance variable (@args
), things would work the way you expect. In other words, while inheriting from theStruct
will give youargs
andargs=
methods, it won't give you an@args
instance variable.