更新不可变对象

JAS*_*SON 2 functional-programming scala purely-functional

我有以下类:

class Player(val name: String, val onField: Boolean, val draft: Int, val perc: Int, val height: Int, val timePlayed: Int) {
override def toString: String = name
Run Code Online (Sandbox Code Playgroud)

}

我正在努力做到

def play(team: List[Player]): List[Player] =
team map (p => new Player(p.name, p.onField, p.draft, p.perc, p.height, p.timePlayed + 1))
Run Code Online (Sandbox Code Playgroud)

这实际上是将字段"timePlayed"递增1,并返回播放器的新"列表".

有更方便的方法吗?也许:

def play(team: List[Player]): List[Player] =
team map (p => p.timeIncremented())
Run Code Online (Sandbox Code Playgroud)

我的问题是如何以更方便的方式实现timeIncremented()?所以我不必这样做:

new Player(p.name, p.onField, p.draft, p.perc, p.height, p.timePlayed + 1)
Run Code Online (Sandbox Code Playgroud)

谢谢!

Ser*_*nko 7

您可以使用define Player作为case class并使用编译器生成的方法copy:

case class Player(name: String, onField: Boolean, draft: Int, perc: Int, height: Int, timePlayed: Int) {
    override def toString: String = name
}

def play(team: List[Player]): List[Player] =
    team map (p => p.copy(timePlayed = p.timePlayed + 1))
Run Code Online (Sandbox Code Playgroud)

此外,如您所见,val默认情况下,构造函数参数.

你可以定义timeIncremented的Player,并使用它完全按照你想要的:

case class Player(name: String, onField: Boolean, draft: Int, perc: Int, height: Int, timePlayed: Int) {
    override def toString: String = name
    def timeIncremented: Player = copy(timePlayed = this.timePlayed + 1)
}

def play(team: List[Player]): List[Player] =
    team map (_.timeIncremented)
Run Code Online (Sandbox Code Playgroud)

对于更复杂的情况,你可以看一下镜头:
http://akisaarinen.fi/blog/2012/12/07/boilerplate-free-functional-lenses-for-scala/
更新嵌套结构的清洁方法