简述
我通过试错法解决了这个问题,但显然我的理解中星号操作符和 pp
方法始终给出与我认为的不同的对象。我想了解这种差异,并找到更好的方法来合并哈希数组。我也想在将来能够更有效地调试这种情况。
首先是代码示例和调试步骤。我还提供了我的比较满意的解决方案和更详细的问题描述。
代码
我使用的是 MRI Ruby 2.6.2。给定类 Foo,我期望 Foo#windows 返回一个已合并的哈希。以下是该类的最小示例:
class Foo
attr_reader :windows
def initialize
@windows = {}
end
def pry
{ pry: "stuff pry\r" }
end
def irb
{ irb: "stuff irb\r" }
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中得到一个异常:
TypeError: no implicit conversion of Array into Hash
然而,如果我使用单例方法修改实例以捕获*hashes
参数的值,我可以看到一组哈希表,我可以很好地合并。请考虑以下内容:
def foo.windows= *hashes
pp *hashes
end
foo.windows = foo.pry, foo.irb
#=> [{:pry=>"stuff pry\r"}, {:irb=>"stuff irb\r"}]
{}.merge *[{:pry=>"stuff pry\r"}, {:irb=>"stuff irb\r"}]
#=> {:pry=>"stuff pry\r", :irb=>"stuff irb\r"}
从#pp获取输出会得到我期望的东西。然而,当我深入挖掘时,发现有些东西额外嵌套了一个Hash层级:
def foo.windows= *hashes
pp *hashes.inspect
end
foo.windows = foo.pry, foo.irb
"[[{:pry=>\"stuff pry\\r\"}, {:irb=>\"stuff irb\\r\"}]]"
尽管返回值并未显示,但多了一对方括号使得数组嵌套。我真的不明白它们是从哪里来的。
可行方案
所以,出于某种原因,我必须将该数组打散、展平,然后才能合并:def foo.windows= *hashes
@windows.merge! *hashes.flatten
end
# The method still returns unexpected results here, but...
foo.windows = foo.pry, foo.irb
#=> [{:pry=>"stuff pry\r"}, {:irb=>"stuff irb\r"}]
# the value stored in the instance variable is finally correct!
foo.windows
#=> {:pry=>"stuff pry\r", :irb=>"stuff irb\r"}
为什么会这样?
是的,我已经成功解决了这个问题。然而,我的问题实际上是关于 为什么 合并哈希值没有按照预期工作,并且额外的嵌套层是从哪里来的。我不希望得到一个哈希值数组的数组,而是要得到一个哈希值数组。是我对此的理解有误,还是这是某种奇怪的边角案例?
更重要的是,为什么这么难调试呢?我期望 #pp 或 #inspect 显示我真正拥有的对象,而不是显示一个哈希值数组的返回值,而我明显拥有一个包含哈希值的数组。
h1, h2
转换成一个单一的值。星号 “*” 将可变参数移入一个数组中——由于它只接收到一个单一的值,你会看到嵌套的结果。例如,https://dev59.com/vGox5IYBdhLWcg3wVCxy - Dave Newton