3

Often when programming in Ruby, I find myself writing small for loops with a single statement in the body. For example...

for number in 1..10
  puts number
end

In other languages like C, Java or Kotlin (for example), I'd be able to write the same code in two lines. For example...

// Kotlin
for (number in 1..10)
    println(number)

In the above example, the ending of the loop body is inferred due to the lack of curly braces.

Does Ruby have a way to imitate this "single-statement" style of "for loop"?

Here are some of [my options/your potential replies], along with my thoughts on them.

  • You could append ; end to the body to end it on the same line.

    This is true, and pretty sufficient, but I'd like to know if there's a more idiomatic approach.

  • This seems unnecessarily picky. Why would you ever want to do this?

    You may think I'm being too picky. You may also think what I'm trying to do is un-idiomatic (if that's even a word). I totally understand, but I'd still love to know if it's do-able!

    Doing this could let us write code that's even just a tiny bit nicer to read. And for programmers, readability matters.

2
  • 2
    The infamous "goto fail" feature. Commented Dec 28, 2016 at 9:50
  • @Stefan I think heartbleed had a similar issue with missing curly braces. The last company I worked for required them to be there. I like the shortness of excluding them though, and I do TDD so I'm very unlikely to get caught by an unexpected bug like that. Commented Dec 28, 2016 at 17:30

3 Answers 3

9

Sure, you're looking for each, Range#each in this particular case:

(1..10).each { |number| puts number }

For more complex iterations use do - end block syntax. For example

(1..10).each do |number|
  puts number
  some_method_call(number)
  Rails.logger.info("The #{number} is used")
  something_else
end

To find more check out Ruby documentation, in particular, see Enumerable.

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

10 Comments

This is quite nice, although I find it a little unusual to read. Will it appear more natural the more I use it?
@BrandonIbbotson Yes it will. The for loop really never needs to be used in ruby.
@BrandonIbbotson absolutely. This is the conventional way to iterate over a collection in Ruby
Perfect & thank you! I'll mark your answer as accepted after 10 minutes (assuming nobody else comes along and writes a better answer) ;)
@BrandonIbbotson yep :) Also, use {} for one liner, if you need to do something more complex inside the block, use do end block, inside of which you can use new line to do new operation while being in the same iteration
|
2

There is an even shorter syntax.

If you are just calling one method on each object you can use & syntax.

(1..3).collect(&:odd?) # => [true, false, true]

This is the same as

(1..3).collect { |each| each.odd? } # => [true, false, true]

This is the preferred way of writing loops in Ruby.

You'll quickly get used to both & and {} block syntax and the enumeration methods defined in Enumerable module. Some useful methods are

  • each which evaluates the block for each element
  • collect which create new array with the result from each block
  • detect which returns the first element for which block results true
  • select which create new array with elements for which block results true
  • inject which applies "folding" operation, eg sum = (1..10).inject { |a, b| a + b }

Fun fact, style guides for production code usually ban for loops at all because of a subtle but dangerous scoping issue. See more here, https://stackoverflow.com/a/41308451/24468

Comments

2

There is a vanishingly tiny number of cases, where any self-respecting Ruby programmer would even write an explicit loop at all. The number of cases where that loop is a for loop is exactly zero. There is no "more idiomatic" way to write a for loop, because for loops are non-idiomatic, period.

Comments

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.