Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About the inject method: How does it work?

Tags:

ruby

This part of code calculates the value of each arithmetic series up to and including the number that the user put in:

print "enter a number: "
num = gets.to_i
(1..num).inject(0) do |res, e|
  res += e
  p res
end

I think that (1..num) is the range, with num being the user input. I know that inject combines all elements of enum by applying a binary operation specified by a block or a symbol that names a method or operator.

I don't understand what each element in this line does:

(1..num).inject(0) do |res, e|
  • What does |res, e| mean? It must be the block that defines what inject does, but what does for instance res and e stand for? (e is probably element?)
  • What does (0) stand for?
  • What does the command do do?
  • what is its connection in regard to (1..num) and inject(0)?
  • Am I right to assume that p at the end just stands for puts or print?
like image 560
Vroryn Avatar asked Jan 20 '26 17:01

Vroryn


1 Answers

inject takes an optional start value, and a block taking an intermediate value and element and returning a new intermediate value.

So:

What does (0) stand for?

The start value parameter to inject.

What does the command "do" do?

It is not a command; it marks the start of the block (terminated by end). .inject(0) do ... end is almost (except for some syntactic issues) the same as .inject(0) { ... }. Usually, do ... end is used for multi-line blocks and { ... } for single-line blocks, but it is not a rule.

What does |res, e| mean?

Those are the block parameters (intermediate value and current element), here probably called after "result" and "element", respectively.

Let's see on a simplified example: (1..3).inject(0) do |res, e| res + e end will set the intermediate result to 0. Then it will pass this intermediate result and the first element of the enumerable being injected: res is 0 and e is 1. The value of the block is the value of its last expression, which is 1 (result of 0 + 1). This 1 now becomes the new intermediate value, and 2 becomes the next current element. The value of the block is 3 (result of 1 + 2). In the next iteration, intermediate value is 3, and the current element also 3, resulting in 6 (3 + 3). The range will stop yielding elements now that we reached its upper boundary, and inject returns with the last intermediate result calculated, 6.

Also, the last question am I right to assume that "p" at the end just stands for puts or print?

Almost. p is its own beast. p x is roughly synonymous with puts x.inspect; x - i.e. it prints the value in a bit different format, and unlike puts which always returns nil, p returns the value unchanged. Thus, p res at the end of your block will not destroy the code by making it return nil, but transparently return res.

like image 76
Amadan Avatar answered Jan 22 '26 12:01

Amadan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!