byxor
byxor

Reputation: 6349

Is it possible to write a single-statement for loop in two lines with Ruby?

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.

Upvotes: 3

Views: 2466

Answers (3)

Jörg W Mittag
Jörg W Mittag

Reputation: 369428

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.

Upvotes: 2

akuhn
akuhn

Reputation: 27793

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

Upvotes: 2

Andrey Deineko
Andrey Deineko

Reputation: 52357

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.

Upvotes: 9

Related Questions