einige verschachtelte Fall Klassen definiert mit List
Feldern:Wie finden und ändern Sie das Feld in geschachtelten Fallklassen?
@Lenses("_") case class Version(version: Int, content: String)
@Lenses("_") case class Doc(path: String, versions: List[Version])
@Lenses("_") case class Project(name: String, docs: List[Doc])
@Lenses("_") case class Workspace(projects: List[Project])
und eine Probe workspace
:
val workspace = Workspace(List(
Project("scala", List(
Doc("src/a.scala", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.scala", List(Version(1, "b11"), Version(2, "b22"))))),
Project("java", List(
Doc("src/a.java", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.java", List(Version(1, "b11"), Version(2, "b22"))))),
Project("javascript", List(
Doc("src/a.js", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.js", List(Version(1, "b11"), Version(2, "b22")))))
))
Jetzt möchte ich, ein solches Verfahren schreiben, die eine neue version
zu einem doc
hinzu:
def addNewVersion(workspace: Workspace, projectName: String, docPath: String, version: Version): Workspace = {
???
}
Ich werde wie folgt verwendet:
val newWorkspace = addNewVersion(workspace, "scala", "src/b.scala", Version(3, "b33"))
println(newWorkspace == Workspace(List(
Project("scala", List(
Doc("src/a.scala", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.scala", List(Version(1, "b11"), Version(2, "b22"), Version(3, "b33"))))),
Project("java", List(
Doc("src/a.java", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.java", List(Version(1, "b11"), Version(2, "b22"))))),
Project("javascript", List(
Doc("src/a.js", List(Version(1, "a11"), Version(2, "a22"))),
Doc("src/b.js", List(Version(1, "b11"), Version(2, "b22")))))
)))
Ich bin nicht sicher, wie man es auf eine elegante Art und Weise implementiert. Ich versuchte mit monocle, aber es stellt filter
oder find
nicht zur Verfügung. Meine peinliche Lösung ist:
def addNewVersion(workspace: Workspace, projectName: String, docPath: String, version: Version): Workspace = {
(_projects composeTraversal each).modify(project => {
if (project.name == projectName) {
(_docs composeTraversal each).modify(doc => {
if (doc.path == docPath) {
_versions.modify(_ ::: List(version))(doc)
} else doc
})(project)
} else project
})(workspace)
}
Gibt es eine bessere Lösung? (Kann alle Bibliotheken verwenden, nicht nur monocle
)