为什么Hash#使用splat运算符合并返回Hashes数组而不是Hashes数组
TL; DR
我通过反复试验解决了这个问题,但是我对splat运算符和pp方法如何一直给我一个不同于我认为的对象的理解显然存在差距.我想了解这个差距,并找出合并散列数组的更好方法.我也希望能够在未来更有效地调试这类事情. 首先是代码示例和调试步骤.我的半满意解决方案和更详细的问题都在底部. 代码 我正在使用MRI Ruby 2.6.2.鉴于Foo类,我希望Foo #windows返回一个合并的哈希值.这是该类的最小示例: class Foo attr_reader :windows def initialize @windows = {} end def pry { pry: "stuff pryr" } end def irb { irb: "stuff irbr" } end def windows= *hashes @windows.merge! *hashes end end foo = Foo.new foo.windows = foo.pry,foo.irb 问题(带调试) 但是,尝试分配给foo.windows(或者甚至试图通过foo.windows = foo.pry,foo.irb来帮助解析器时不那么模糊)我从REPL获得了一个异常:
但是,如果我使用单例方法修改实例来捕获* hashes参数的值,我会看到一个哈希数组,我可以合并得很好.考虑以下: def foo.windows= *hashes pp *hashes end foo.windows = foo.pry,foo.irb #=> [{:pry=>"stuff pryr"},{:irb=>"stuff irbr"}] {}.merge *[{:pry=>"stuff pryr"},{:irb=>"stuff irbr"}] #=> {:pry=>"stuff pryr",:irb=>"stuff irbr"} 从#pp获取输出给了我一些按预期工作的东西.然而,当我深入挖掘时,事实证明有些东西正在层叠在Hash的额外嵌套上: def foo.windows= *hashes pp *hashes.inspect end foo.windows = foo.pry,foo.irb
即使返回值没有显示,也有一组额外的方括号导致数组嵌套.我真的不明白他们来自哪里. 什么有用 因此,无论出于何种原因,我必须将数据展开,展平它,然后我就能合并: def foo.windows= *hashes @windows.merge! *hashes.flatten end # The method still returns unexpected results here,but... foo.windows = foo.pry,{:irb=>"stuff irbr"}] # the value stored in the instance variable is finally correct! foo.windows #=> {:pry=>"stuff pryr",:irb=>"stuff irbr"} 但为什么? 所以是的,我已经设法解决了这个问题.但是,我的问题是关于为什么合并散列不能按预期工作,以及额外的嵌套层来自何处.我不期望哈希数组数组,而是哈希数组.我的理解是否存在差距,或者这是某种奇怪的边缘情况? 更重要的是,为什么这么难以调试?我希望#pp或#inspect向我展示我真正拥有的对象,而不是在我清楚地拥有包含Hash的数组数组时向我显示一个Hashes数组作为返回值. 解决方法
你错过的是
Ruby parser doesn’t allow setter methods with more than one parameter.
当您将多个参数传递给setter时,它们会自动放在一个数组上(因为a = 1,2表示与a = [1,2]相同): def foo.a=(values) pp values end foo.a = 1,2 # [1,2] 但是,如果定义了splat参数,因为该数组被认为是单个参数,所以会发生这种情况: def foo.a=(*values) pp values end foo.a = 1,2 # [[1,2]] (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |