131

In Scala, you often use an iterator to do a for loop in an increasing order like:

for(i <- 1 to 10){ code }

How would you do it so it goes from 10 to 1? I guess 10 to 1 gives an empty iterator (like usual range mathematics)?

I made a Scala script which solves it by calling reverse on the iterator, but it's not nice in my opinion, is the following the way to go?

def nBeers(n:Int) = n match {

    case 0 => ("No more bottles of beer on the wall, no more bottles of beer." +
               "\nGo to the store and buy some more, " +
               "99 bottles of beer on the wall.\n")

    case _ => (n + " bottles of beer on the wall, " + n +
               " bottles of beer.\n" +
               "Take one down and pass it around, " +
              (if((n-1)==0)
                   "no more"
               else
                   (n-1)) +
                   " bottles of beer on the wall.\n")
}

for(b <- (0 to 99).reverse)
    println(nBeers(b))

7 Answers 7

255
scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
Sign up to request clarification or add additional context in comments.

3 Comments

@Felix: You're welcome. I should have also pointed out that there is also until that you can use in place of to to exclude the right-hand end-point from the range. The left-hand endpoint is always included.
I already knew about the until, the until is also a function on Integers, however, "by" must be a function on the range/iterator whatever is returned from the "to" and "until" functions. Thanks anyway :)
Randall's answer is best, but I think Range.inclusive(10, 1, -1) deserves mention.
44

The answer from @Randall is good as gold, but for sake of completion I wanted to add a couple of variations:

scala> for (i <- (1 to 10).reverse) {code} //Will count in reverse.

scala> for (i <- 10 to(1,-1)) {code} //Same as with "by", just uglier.

3 Comments

+1 for first one one, but second one is evil -- less readable than by and IMO shouldn't be used under any circumstances
Second one is evil but builds intuition on what's available
Thanks, reverse is nice for exclusive start and inclusive end e.g. 1 until x reverse instead of x - 1 to 1 by -1.
16

Scala provides many ways to work on downwards in loop.

1st Solution: with "to" and "by"

//It will print 10 to 0. Here by -1 means it will decremented by -1.     
for(i <- 10 to 0 by -1){
    println(i)
}

2nd Solution: With "to" and "reverse"

for(i <- (0 to 10).reverse){
    println(i)
}

3rd Solution: with "to" only

//Here (0,-1) means the loop will execute till value 0 and decremented by -1.
for(i <- 10 to (0,-1)){
    println(i)
}

Comments

6

Having programmed in Pascal, I find this definition nice to use:

implicit class RichInt(val value: Int) extends AnyVal {
  def downto (n: Int) = value to n by -1
  def downtil (n: Int) = value until n by -1
}

Used this way:

for (i <- 10 downto 0) println(i)

2 Comments

Thank your for the answer. I'm having trouble using this solution. Here is my stacktrace: Error:(57, 17) value class may not be a member of another class implicit class RichInt(val value: Int) extends AnyVal { ^
As the error message (not a stack trace) suggests, you cannot define the value class inside of another class. Either define it outside of it, oike in an object, or remove the extends AnyVal part (which only serves to remove some overhead).
2

You can use Range class:

val r1 = new Range(10, 0, -1)
for {
  i <- r1
} println(i)

Comments

2

You can use : for (i <- 0 to 10 reverse) println(i)

Comments

1
for (i <- 10 to (0,-1))

The loop will execute till the value == 0, decremented each time by -1.

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.