10

In the language Ruby the following works in irb

for fruit in ['apple', 'banana', 'cherry', 'date'] do
    puts fruit 
end

but this one does not

# error
for fruit in ['apple', 'banana', 'cherry', 'date'] { puts fruit } 

please note for reference the following block delimiters do not error

5.times do |i|
    puts "hello "+i.to_s
end

5.times { |i| puts "hello "+i.to_s }

Edit: I guess what I'm observing is an inconsistency with the way do end is substituted for { } can someone explain why or please point out my mistake?

5
  • don't know why, but there is a similar restriction in refine <class> do as well. Commented Dec 29, 2016 at 5:16
  • If it's any consolation, you don't need the opening do in a for loop. Commented Dec 29, 2016 at 5:31
  • This might be to do with the fact that for and while (which acts like for) are not methods. But I await a formal reasoning. Commented Dec 29, 2016 at 5:43
  • 2
    This is a perfect example of why we should always avoid and consider being a code smell for and while loops in ruby. Commented Dec 29, 2016 at 6:56
  • I cannot find where for is defined in the official Ruby doc. Does somebody know where it is? Commented Dec 29, 2016 at 10:25

2 Answers 2

10

The following quote from this post explains the "inconsistency" well (emphasis mine):

end is a generic keyword that ends a context (conditionals, class and module definitions, method definitions, loops and exception-catching [statements]). Curly braces are special syntax for defining blocks or Hashes.

for loops are control structures - not methods with a block argument - hence they must be closed with the end keyword. Methods such asEnumerable#times and Enumerable#each have a block argument which can be defined with either of the { } or do ... end syntaxes.

Sign up to request clarification or add additional context in comments.

1 Comment

great answer! Thanks.
0

for isn't a method defined for Object or in Kernel, and it doesn't expect a block.

You cannot write :

class A {
  def method {
  }
}

either.

You could define a custom my_for method :

module Kernel
  def my_for(elements, &block)
    elements.each(&block)
  end
end

my_for ['apple','banana','cherry', 'date'] do |fruit|
  puts fruit
end

my_for ['apple','banana','cherry', 'date'] { |fruit| puts fruit }

1 Comment

for ... in is a valid control expression in Ruby, see the documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.