我在下面的代碼中遇到了一個最令人不安的錯誤。即使我將它作爲不可變的Map傳遞,按鈕Map也會發生變異。按鍵保持不變,並且地圖指向兩個不可變的Ints,但在下方,您可以看到地圖在運行過程中顯然具有不同的值。我絕對難住,不知道發生了什麼。爲什麼我的不可變對象突變Scala
def makeTrace(trace : List[(String)], buttons : Map[String, (Int,Int)],
outputScreen : ScreenRegion, hashMap : Map[Array[Byte], String])
: (List[(String,String)], Map[Array[Byte], String]) = {
println(buttons.toString)
//clearing the device
val clear = buttons.getOrElse("clear", throw new Exception("Clear Not Found"))
//clear.circle(3000)
val thisButton = new ScreenLocation(clear._1, clear._2)
click(thisButton)
//updates the map and returns a list of (transition, state)
trace.foldLeft((Nil : List[(String,String)], hashMap))((list, trace) => {
println(buttons.toString)
val transition : String = trace
val location = buttons.getOrElse(transition, throw new Exception("whatever"))
val button = new ScreenLocation(location._1, location._2)
button.circle(500)
button.label(transition, 500)
click(button)
//reading and hashing
pause(500)
val capturedImage : BufferedImage = outputScreen.capture()
val outputStream : ByteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(capturedImage, "png", outputStream)
val byte : Array[Byte] = outputStream.toByteArray();
//end hash
//if our state exists for the hash
if (hashMap.contains(byte)){ list match {
case (accumulator, map) => ((transition , hashMap.getOrElse(byte, throw new Exception("Our map broke if"))):: accumulator, map)
}
//if we need to update the map
}else list match {
case (accumulator, map) => {
//adding a new state based on the maps size
val newMap : Map[Array[Byte], String] = map + ((byte , "State" + map.size.toString))
val imageFile : File = new File("State" + map.size.toString + ".png");
ImageIO.write(capturedImage, "png", imageFile);
((transition, newMap.getOrElse(byte, throw new Exception("Our map broke else"))) :: accumulator, newMap)
}
}
})
}
之前,我調用這個函數初始化我的地圖指向不可變對象的不可變映射。
val buttons = makeImmutable(MutButtons)
val traceAndMap = TraceFinder.makeTrace(("clear" ::"five"::"five"::"minus"::"five"::"equals":: Nil), buttons, outputScreen, Map.empty)
哪裏makeImmutable是
def makeImmutable(buttons : Map[String, (Int,Int)]) : Map[String, (Int,Int)] = {
buttons.mapValues(button => button match {
case (x, y) =>
val newX = x
val newY = y
(newX,newY)
})
}
這裏是輸出,你可以看到清晰的狀態變化,減,五
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (959,345), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (881,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,441), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (881,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
Map(equals -> (959,425), clear -> (842,313), minus -> (920,409), five -> (842,377))
要麼地圖必須變異,要麼地圖上的* objects *必須是變異的。沒有明智的選擇。找出哪些 - 慢慢刪除所有不必要的代碼,使問題依然存在。 (好吧,我想這可能是一個不同的地圖打印在某處..) – 2013-03-16 21:02:12
我無法弄清格式,但我會在上面插入它。我在調用函數之前立即做的是用不可變的對象創建一個不可變的映射。我將發佈上面的代碼。 – dakillakan 2013-03-16 21:05:54