Array.first Vs Array.shift in Ruby

I basically do the exercise to rewrite the basic form of the injection method from the Enumerable module, and my solution did nothing, since I used #first:

def injecting(*acc, &block)
  acc = acc.empty? ? self.first : acc.first
  self.each do |x|
     acc = block.call(acc, x)
  end  
  acc
end

Then I came across another solution that used #shift instead of #first and worked fine:

def injecting(*acc, &block)
  acc = acc.empty? ? self.shift : acc.first
  self.each do |x|
    acc = block.call(acc, x)
  end  
  acc
end  

I know that # the first returns the first element of the array, but does not change it, and #shift returns and changes it, but it’s hard for me to understand how the code below will still get the desired result if you were to mutate the array by discarding the first element:

[1,2,3].injecting { |a,x| a + x } # --> 6

Any words of wisdom will be greatly appreciated.

Thanks!

+4
source share
1 answer

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 6. , 6.

:

(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
>>

OP

, 1- , , 7?

, , . :

(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.. 3 self, 1, 2 3. 6 1, acc, self.first. acc 7.

+4

Source: https://habr.com/ru/post/1524861/


All Articles