Is this a pure function in Scala

The getRandomString function getRandomString generates a random string from a list of characters:

  def genRandomInt(lb: Int, ub: Int) = { val rnd = new scala.util.Random lb + rnd.nextInt(ub) } def getRandomString(validChars: List[Char]) = { val size = validChars.size val random = new scala.util.Random val stringBuilder = new StringBuilder val rnd = genRandomInt(0, size) val sb = new StringBuilder for (i <- 0 to size - 1) { val rnd = genRandomInt(0, size) sb.append(validChars(rnd)) } sb.toString } //> getRandomString: (validChars: List[Char])String val rs = getRandomString(('a' to 'j').toList) //> rs : String = aghdjjhjge 

Is getRandomString an example of a pure function since it does not change state?

+5
source share
2 answers

No, because it really modifies the state. new scala.util.Random ultimately calls new java.util.Random , which accesses and modifies the static (i.e. global) mutable AtomicLong called seedUniquifier . And therefore, if this method is called several times, the result will change.

This is a good example of how innocent methods can hide access to global mutable state, which would be forbidden in a more rigorous functional language like Haskell (although this approach has its own problems).

+8
source

No, because new scala.util.Random().nextInt ... returns something else every time, which is convincingly explained by Him.

However, you can just pass the seed, then it will be a pure function, because it will return the same random string every time. You can add the seed as a parameter or just fix it inside the random string method.

Finally, I noticed that you wrote a huge amount of code to create a random string. I suggest you take a look at ScalaCheck, which has many useful functions for generating random things (for unit tests), String comes out of the box.

If you don't want to pull in the library, you can still make this code more concise:

 def randomString(fromChars: List[Char], length: Int): String = { val rand = new Random(1234) // Now it pure functional because the seed is fixed val fromCharsSize = fromChars.size // to save us repeatedly counting List.fill(length)(fromChars(rand.nextInt(fromCharsSize))).mkString } 

Watch it return the same value every time

 scala> randomString("asdf".toList, 10) res0: String = dsfafssdsa scala> randomString("asdf".toList, 10) res1: String = dsfafssdsa 
+1
source

Source: https://habr.com/ru/post/1209556/


All Articles