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?
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.
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.
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}
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With