List
定义了一些带有字段的嵌套案例类:
@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])
和一个样本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")))))
))
现在我想写一个这样的方法,它添加一个新version
的 a doc
:
def addNewVersion(workspace: Workspace, projectName: String, docPath: String, version: Version): Workspace = {
???
}
我将按如下方式使用:
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")))))
)))
我不确定如何以优雅的方式实现它。我试过monocle,但它没有提供filter
or find
。我尴尬的解决方案是:
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)
}
有没有更好的解决方案?(可以使用任何库,不仅如此monocle
)