Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Print Inject Do Syntax

Why is it that the following code runs fine

p (1..1000).inject(0) { |sum, i|     sum + i } 

But, the following code gives an error

p (1..1000).inject(0) do |sum, i|     sum + i end  warning: do not use Fixnums as Symbols in `inject': 0 is not a symbol (ArgumentError) 

Should they not be equivalent?

like image 830
Verhogen Avatar asked Jan 24 '10 16:01

Verhogen


People also ask

What does Ruby inject do?

You can use the INJECT method to help you quickly sort through the elements of an array and choose the elements you want to build a new array. Here, we're asking Ruby to build us a new array of even numbers from the set we defined earlier.

What does :+ mean in Ruby?

inject accepts a symbol as a parameter, this symbol must be the name of a method or operator, which is this case is :+ so [1,2,3]. inject(:+) is passing each value to the method specified by the symbol, hence summing all elements in the array.

What does #{} mean in Ruby?

It is for String InterpolationString InterpolationIn computer programming, string interpolation (or variable interpolation, variable substitution, or variable expansion) is the process of evaluating a string literal containing one or more placeholders, yielding a result in which the placeholders are replaced with their corresponding values.https://en.wikipedia.org › wiki › String_interpolationString interpolation - Wikipedia.. In Ruby, there are three ways of interpolation, and #{} is just one way. apples = 4 puts "I have #{apples} apples" # or puts "I have %s apples" % apples # or puts "I have %{a} apples" % {a: apples}


2 Answers

The block written using the curly braces binds to the inject method, which is what your intention is, and it will work fine.

However, the block that is encapsulated in the do/end block, will bind to the p-method. Because of this, the inject call does not have an associated block. In this case, inject will interpret the argument, in this case 0, as a method name to call on every object. Bacuase 0 is not a symbol that can be converted into a method call, this will yield a warning.

like image 141
wvanbergen Avatar answered Sep 30 '22 07:09

wvanbergen


The problem is with the p at the beginning. If you omit these you'll see that both work fine:

# Works! [5, 6, 7].inject(0) do |sum, i| # Correctly binds to `inject`.   sum + i end  # Works too! [5, 6, 7].inject(0) { |sum, i|  # Correctly binds to `inject`.   sum + i } 

But this won't work:

# Kablammo! "p" came first, so it gets first dibs on your do..end block. # Now inject has no block to bind to! p [5, 6, 7].inject(0) do |sum, i|   # Binds to `p` -- not what you wanted.   sum + i end 
like image 36
John Feminella Avatar answered Sep 30 '22 05:09

John Feminella