gpt4 book ai didi

list - Scala 对象不改变其内部状态

转载 作者:行者123 更新时间:2023-12-05 00:38:34 24 4
gpt4 key购买 nike

我发现我正在处理的某些 Scala 2.7.7 代码存在问题,如果等效代码是用 Java 编写的,则不会发生这种情况。松散地,代码会创建一堆纸牌玩家并将他们分配给 table 。

class Player(val playerNumber : Int)

class Table (val tableNumber : Int) {
var players : List[Player] = List()

def registerPlayer(player : Player) {
println("Registering player " + player.playerNumber + " on table " + tableNumber)
players = player :: players
}
}

object PlayerRegistrar {
def assignPlayersToTables(playSamplesToExecute : Int, playersPerTable:Int) = {
val numTables = playSamplesToExecute / playersPerTable
val tables = (1 to numTables).map(new Table(_))
assert(tables.size == numTables)

(0 until playSamplesToExecute).foreach {playSample =>
val tableNumber : Int = playSample % numTables
tables(tableNumber).registerPlayer(new Player(playSample))
}
tables
}
}

PlayerRegistrar 在 table 之间分配一定数量的玩家。首先,它计算出需要多少张 table 才能将玩家分开并创建一张 table 列表。

然后在代码的第二部分,它计算出应该将玩家分配到哪个牌 table ,从列表中拉出该牌 table 并在该牌 table 上注册一个新玩家。

table 上的玩家列表是一个变量,每次调用 registerPlayer() 时都会被覆盖。我已经通过简单的 TestNG 测试检查了它是否正常工作:

@Test def testRegisterPlayer_multiplePlayers() {
val table = new Table(1)
(1 to 10).foreach { playerNumber =>
val player = new Player(playerNumber)
table.registerPlayer(player)
assert(table.players.contains(player))
assert(table.players.length == playerNumber)
}
}

然后我测试表分配:

  @Test def testAssignPlayerToTables_1table() = {
val tables = PlayerRegistrar.assignPlayersToTables(10, 10)
assertEquals(tables.length, 1)
assertEquals(tables(0).players.length, 10)
}

测试失败,显示“expected:<10> but was:<0>”。我一直在摸不着头脑,但无法弄清楚为什么 registerPlayer() 没有改变列表中的表。任何帮助将不胜感激。

最佳答案

原因是在 assignPlayersToTables 方法中,您正在创建一个新的 Table 对象。您可以通过在循环中添加一些调试来确认这一点:

val tableNumber : Int = playSample % numTables
println(tables(tableNumber))
tables(tableNumber).registerPlayer(new Player(playSample))

产生类似的东西:

Main$$anon$1$Table@5c73a7ab
Registering player 0 on table 1
Main$$anon$1$Table@21f8c6df
Registering player 1 on table 1
Main$$anon$1$Table@53c86be5
Registering player 2 on table 1

请注意每次调用时表的内存地址是如何不同的。

此行为的原因是 Range 在 Scala 中是非严格的(无论如何,直到 Scala 2.8)。这意味着直到需要时才评估对范围的调用。所以你认为你得到的是 Table 对象的列表,但实际上你得到的是一个范围,每次你都计算(实例化一个新的 Table 对象)叫它。同样,您可以通过添加一些调试来确认这一点:

val tables = (1 to numTables).map(new Table(_))
println(tables)

这给了你:

RangeM(Main$$anon$1$Table@5492bbba)

要做你想做的,在末尾添加一个toList:

val tables = (1 to numTables).map(new Table(_)).toList

关于list - Scala 对象不改变其内部状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2173137/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com