以这段代码为例:
class Thing
attr_accessor :options, :list
def initialize
@list = []
@options = { published_at_end: 'NOW', published_at_start: 'NOW-2DAYS' }
end
def run
# If you replace this comment with a debugger, the value of list is nil
list += _some_method(options)
return list
end
private
def _some_method(options)
[options[:published_at_start], 1, 2, 3, 4, options[:published_at_end]]
end
end
Run Code Online (Sandbox Code Playgroud)
如果将其复制/粘贴到irb中,则运行:
t = Thing.newt.run它会输出这个错误:
NoMethodError: undefined method `+' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)
如果删除+=线(只留下return线),它返回[]......所以从我可以告诉,它只是存在+=,设置list到nil.我也觉得有趣的是它的值nil在调用之前的行中+=(参见我在代码示例中的注释).
另外,如果使用<<具有flatten相反,你会得到预期的结果:
class Thing
attr_accessor :options, :list
def initialize
@list = []
@options = { published_at_end: 'NOW', published_at_start: 'NOW-2DAYS' }
end
def run
list << _some_method(options)
list.flatten
end
private
def _some_method(options)
[options[:published_at_start], 1, 2, 3, 4, options[:published_at_end]]
end
end
Run Code Online (Sandbox Code Playgroud)
如果将其复制/粘贴到irb中,则运行:
t = Thing.newt.run它会输出['NOW-2DAYS', 1, 2, 3, 4, 'NOW'].
为什么+=重置价值list来nil?另外,它如何nil在+=被调用之前设置其值?
半相关/有用的注意事项 - 由于性能原因,我将使用shovel(<<),但我仍然感兴趣为什么变量被重置为.flattennil
list += [1, 2, 3] 相当于:
list = list + [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
因为这是一个赋值,Ruby会创建一个新的局部变量 list,遮蔽你的list方法.从文档:
使用方法分配时,您必须始终拥有接收器.如果您没有接收器,Ruby假定您正在分配一个局部变量
更具体地说,list在解析器遇到时创建局部变量list =.与未初始化的实例变量和全局变量一样,它的值为nil.因此,尝试评估作业的右侧list + [1, 2, 3]是失败的,因为它等同于:
nil + [1, 2, 3]
# NoMethodError: undefined method `+' for nil:NilClass
Run Code Online (Sandbox Code Playgroud)
因此,要获得预期的结果,您必须提供一个明确的接收器:
self.list += [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
或者直接分配给实例变量:
@list += [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
或者使用修改接收器的方法:
list.concat [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |