我实际上正在进行一项练习,用于从Enumerable模块重写一个基本形式的inject方法,我的解决方案没有做任何事情,因为我正在使用#first:
def injecting(*acc, &block)
acc = acc.empty? ? self.first : acc.first
self.each do |x|
acc = block.call(acc, x)
end
acc
end
然后我遇到了另一个使用#shift而不是#first的解决方案,并且工作得很好:
def injecting(*acc, &block)
acc = acc.empty? ? self.shift : acc.first
self.each do |x|
acc = block.call(acc, x)
end
acc
end
我知道#first返回数组的第一个元素,但是当#shift返回并改变它时不会改变它,但是我很难理解下面的代码如果仍然能得到想要的结果是通过删除第一个元素来改变数组:
[1,2,3].injecting { |a,x| a + x } # --> 6
任何智慧的话都会受到高度赞赏。
谢谢!
答案 0 :(得分:4)
只需添加一行p acc
即可进行调试。
(arup~>~)$ pry --simple-prompt
>> module Enumerable
| def injecting(*acc, &block)
| acc = acc.empty? ? self.shift : acc.first
| p acc
| self.each do |x|
| acc = block.call(acc, x)
| end
| acc
| end
| end
=> nil
>> [1,2,3].injecting { |a,x| a + x }
1
=> 6
>>
当您在数组injecting
上调用方法[1,2,3]
时,由于acc
为空,因此会调用sef.shift
。现在acc
是1
。现在self
只有[2,3]
。所以调用self.each..
首先通过2
,然后调用块,a = x
的结果分配给acc
,现在保持3
。所以现在在下一次迭代中,从self
传递下一个值(3
),再次调用块,再次执行a + x
,所以现在acc
的值为{ {1}}。所以你得到了结果6
。
更多级调试:
6
我安全地假设通过先调用,仍然返回第一项但是从该项开始迭代,因此为什么我会得到7?
我再次建议你添加一些调试信息,看看会发生什么事情。看下面:
(arup~>~)$ pry --simple-prompt
>> module Enumerable
| def injecting(*acc, &block)
| acc = acc.empty? ? self.shift : acc.first
| p "acc now holds #{acc}"
| p "elements in self is #{self}"
| self.each do |x|
| acc = block.call(acc, x)
| p "current value of acc is #{acc}"
| end
| acc
| end
| end
=> nil
>> [1,2,3].injecting { |a,x| a + x }
"acc now holds 1"
"elements in self is [2, 3]"
"current value of acc is 3"
"current value of acc is 6"
=> 6
>>
(arup~>~)$ pry --simple-prompt
>> module Enumerable
| def injecting(*acc, &block)
| acc = acc.empty? ? self.first : acc.first
| p "acc now holds #{acc}"
| p "elements in self is #{self}"
| self.each do |x|
| acc = block.call(acc, x)
| p "current value of acc is #{acc}"
| end
| acc
| end
| end
=> nil
>> [1,2,3].injecting { |a,x| a + x }
"acc now holds 1"
"elements in self is [1, 2, 3]"
"current value of acc is 2"
"current value of acc is 4"
"current value of acc is 7"
=> 7
>>
只返回第一个元素self.first
,然后分配给1
。但是自我没有得到修改。但是在acc
的情况下,self.shift
已被1
分配给acc
,并且在self
已被删除,然后self
已[2,3]
self.each..
}。
现在,在此部分中,self
代码传递了1
的3个值,即2
,3
和6
。现在总和为1
,并在调用acc
时添加了self.first
,这是第一个acc
值。这就是7
的最终结果是{{1}}。