2

Below here the code snippet, where I want to avoid using the 'var'. Not sure if there is a good way to do that

var randomInt = Random.nextInt(100)
private def getRandomInt(createNew:Boolean):Int = {
  if(createNew){
    randomInt = Random.nextInt(100)
  }
  randomInt
}
3
  • 1
    Can you give more context: how will this be used? Commented Oct 14, 2021 at 17:57
  • Short answer, no. Your design is mutable by definition. Commented Oct 14, 2021 at 18:01
  • @GaëlJ I simply need random number generator for a process, where I may want to retrieve the previously generated number in a given scenario and in another scenario, I want a new number. Commented Oct 14, 2021 at 18:20

3 Answers 3

5

Create an "infinite" Iterator of random numbers. Advance to the next() only when needed.

val randomInt = Iterator.continually(Random.nextInt(100)).buffered
private def getRandomInt(createNew:Boolean):Int = {
  if (createNew) randomInt.next()

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

1 Comment

I'm confused. What does it buy? The code with var seems way clearer.
0

The class below holds the current random value and provides a method to return an instance holding the next random value.

It only uses immutable values, although the Random.nextInt(...) function isn't pure, because it doesn't return the same result for the same input.

The class is a direct translation of your 3 requirements:

  1. to retrieve the previously generated number.
  2. to generate a new number.
  3. avoid using the 'var'.

This shows the basic technique of returning a new immutable instance instead of mutating a variable, although I find the infinite iterator answer by jwvh to be a more elegant solution.

import scala.util.Random

// A random number generator that remembers its current value.
case class RandomInt(size: Int) {
  val value = Random.nextInt(size)

  def nextRandomInt(): RandomInt = RandomInt(size)
}

// Test case
object RandomInt {
  def main(args: Array[String]): Unit = {
    val r0 = RandomInt(100)

    (0 to 99).foldLeft(r0)((r, i) => {
      println(s"[$i] ${r.value}")
      r.nextRandomInt()
    })
  }
}

Comments

0

Not sure what changes you are open too, you can simply just add a parameter

val randomInt = Random.nextInt(100)
private def getRandomInt(createNew:Boolean,previous:Int):Int = {
  if(createNew) Random.nextInt(100) else previous
}

3 Comments

Don't think it would be useful because we don't have information about the previous before calling this method at first place. Am I missing anything ?
Not sure what you mean , you have a randomInt var , you simply pass it in getRandomInt(true,randomInt)
The problem is after you have called the function with the 'true' argument as getRandomInt(true,randomInt) then I want to call it with 'false' argument but the caller don't have the information about the 'previous' which is the second argument, as it is called from some other place than the first one and hence it doesn't quite work.

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.