Nat G Nat G - 3 months ago 17
Scala Question

Scala infinite while loop even though condition changed to false

import scala.collection.mutable.ArrayBuffer

object nameList {
val names = ArrayBuffer("placeholder")
}

class Robot {
val r = scala.util.Random
val letters = 'A' to 'Z'
val name = {
val initName = nameList.names(0)
while(nameList.names.contains(initName)){
val initName = letters(r.nextInt(26)).toString + letters(r.nextInt(26)).toString + r.nextInt(10).toString + r.nextInt(10).toString + r.nextInt(10).toString
println("while", initName)
println("while", nameList.names)
println("checker", nameList.names.contains(initName))
}
println("outside", nameList.names)
nameList.names += initName
initName
}
}


outputs

(while,LA079)
(while,ArrayBuffer(placeholder))
(checker,false)
(while,IO176)
(while,ArrayBuffer(placeholder))
(checker,false)


The while loop runs indefinitely, above is an output snippet. Why isn't the while loop exiting even though the condition is changed to false?

Big picture, I need to ensure that each
Robot
instance has a unique
name
--I'm open to alternatives to using a while loop.

Update: per Jason C, below code fixes reassignment problem:

var initName = nameList.names(0)
while(nameList.names.contains(initName) == true){
initName = letters(r.nextInt(26)).toString + letters(r.nextInt(26)).toString + r.nextInt(10).toString + r.nextInt(10).toString + r.nextInt(10).toString

Answer

It's because in your loop:

val initName = ...
while(nameList.names.contains(initName)){
    val initName = ...
    ...
}

You redeclare val initName in the loop. So now you effectively have two different values. The one in the while condition is the outer scoped one. The one declared in the loop has no effect on it.

I don't actually know Scala but from What is the difference between a var and val definition in Scala? I'm guessing the solution is to change the outer one to var (so it's modifiable) and drop the val entirely from the inner one (so you're not redeclaring it).