Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby #inject behavior is different from documentation

Taking a look at Ruby documentation on Enumerable class I noticed something interesting and I'd like to know why it happens this way.

At #inject description I've found these examples:

# Sum some numbers
(5..10).reduce(:+)                             #=> 45
# Same using a block and inject
(5..10).inject { |sum, n| sum + n }            #=> 45
# Multiply some numbers
(5..10).reduce(1, :*)                          #=> 151200
# Same using a block
(5..10).inject(1) { |product, n| product * n } #=> 151200

Notice that when #inject is used for multiplication, it receives an initial value of 1. I thought this was necessary because otherwise product would receive 0 as start value (as it happens in the sum) and the multiplication would also be 0. In fact, if I run

p (1..5).inject(0) { |prod, n| prod * n } 

I got

0

But then I run

p (1..5).inject { |sum, n| sum + n } 
p (1..5).inject { |prod, n| prod * n } 

and got

15
120

My questions are:

a) Why the documentation includes this 1 as initial value when, in fact, it is not needed?

and

b) What is the behavior of #inject when it comes to initializing the object being injected?

like image 820
Ed de Almeida Avatar asked Feb 05 '23 14:02

Ed de Almeida


1 Answers

To answer your first question:

a) Why the documentation includes this 1 as initial value when, in fact, it is not needed?

inject does not take 1 as initial value, from the apidock:

If you do not explicitly specify an initial value for memo, then uses the first element of collection is used as the initial value of memo.

Answer of second question lies in the answer of first itself, as it initialises the object as the first element of array on which inject is being applied.

like image 170
Saurabh Avatar answered Feb 20 '23 09:02

Saurabh