0

Found an interesting quirk in the ruby interpreter - at least in MRI 2.4.2.

As far as I can tell, each of the below code snippets should print '123'. If I try to print the result of reduce directly, I get NoMethodError: undefined method '' for 1:Integer (or whatever type the array contains) But if I first save the result and then print it, it works fine..

So, this code is broken:

puts [1,2,3].reduce('') do |memo, num|
  memo + num.to_s
end

And this code works:

temp = [1,2,3].reduce('') do |memo, num|
  memo + num.to_s
end
puts temp

These should work exactly the same, right? Should this be filed as a bug? Am I just missing something fundamental here?

I'd think it should at least show which method is trying to be called. Can't find anything in google about an undefined method without a method name...

iCodeSometime
  • 1,345
  • 12
  • 29
  • Does the second code snippet work? I am getting `nil`, not sure if that is what you are expecting. – chevybow May 03 '18 at 15:03
  • Yes. temp is successfully set to '123', and puts prints it normally (which also returns nil, is that what you're seeing?) Updated question for clarity – iCodeSometime May 03 '18 at 15:07
  • 2
    This has been asked numerous times already. You are passing the block to `puts`, not to `inject`. – Jörg W Mittag May 03 '18 at 15:29

1 Answers1

1

You need parenthesis on the puts call. This works:

puts([1,2,3].reduce('') do |memo, num|
  memo + num.to_s
end)

Normally you can avoid parenthesis, but sometimes the parser will find ambiguities and will just raise an error, like in your first case.

de-russification
  • 31,008
  • 6
  • 34
  • 52
Simone
  • 18,870
  • 12
  • 73
  • 98
  • Thanks! I guess i can see how it would be ambiguous if puts accepted a block, and reduce didn't require one in this case. Just to be clear, generally, parens are always needed if there should be a block inside the function call? – iCodeSometime May 03 '18 at 15:23
  • @kennycoc I think so, yeah. – Simone May 04 '18 at 09:05