julien-truffaut on gh-pages
Deploy website Deploy website … (compare)
xuwei-k on master
Update scalafmt-core to 3.5.9 (… (compare)
julien-truffaut on gh-pages
Deploy website Deploy website … (compare)
xuwei-k on master
Update sbt-mdoc to 2.3.3 (#1292) (compare)
@Lenses
working on 2.13.6?
.field
(optics-dev/Monocle#1125) but it can be added later
I am trying to create a lens, which accesses different fields in a case class, eg: GenLens[Person](_.details.age)
, GenLens[Person](_.details.address)
, GenLens[Person](_.details.name)
Is there a way I can do this by generalizing the changing field? Something like
val attribute = "name"
GenLens[Person](_.details.$attribute)
I'm really stuck on something ... I'm trying to generate at runtime list of lenses to modify a data structure... here's simplified example:
sealed trait TreeLike
final case class Tree(id: String, leaves: List[Leaf]) extends TreeLike
final case class Leaf(i: Int) extends TreeLike
val tree = Tree(
"t1", List(Leaf(1), Leaf(2), Leaf(3))
)
val treeLens = tree.focus()
val lenses: List[AppliedLens[Tree, Leaf]] = ??? // list of lenses for leaves where i%2 ==0
how would I go about this? Where I essentially need to fold over runtime values to make lenses
btw kickass library
sealed trait TreeLike
final case class Tree(id: String, leaves: List[Leaf]) extends TreeLike
final case class Leaf(num: Int) extends TreeLike
val tree = Tree(
"t1", List(Leaf(1), Leaf(2), Leaf(3), Leaf(4))
)
val lenses: List[Traversal[Tree, Leaf]] =
tree.leaves.map {
x =>
if (x.num % 2 == 0) {
val ff = Focus[Tree](_.leaves)
.andThen(Traversal.fromTraverse[List, Leaf])
.andThen(
Prism[Leaf, Leaf] { bi =>
if (bi == x) Some(bi)
else None
}(identity)
)
Some(ff)
} else None
}.collect { case Some(x) => x }
val res = lenses.foldLeft(tree) { case (t, lens) =>
lens.modify(x => Leaf(x.num + 10))(t)
}
Traversal
(optics that targets many values of the same type), Plated
might also be an option, it deals with recursive data structures like your Tree https://github.com/optics-dev/Monocle/blob/master/example/src/test/scala/monocle/JsonExample.scala#L227-L259
Good evening all!
I was wondering how can I improve upon this manual thing I'm doing now?
Suppose I have a case class Person(name: String, age: Int)
. I receive a PATCH
request, containing optional fields that may have changed. What I'm currently doing is manually building a bunch of Person => Person
functions, either copying over the new value or returning the given person
unchanged, then applying all those "patch" functions one after the other to the initial person
.
Surely there's a better way :slight_smile:
case class PatchPersonRequest(name: Option[String], age: Option[Int])
val request = PatchPersonRequest(...)
val patchName: Person => Person = request.name.fold[Person => Person](identity)(n => p => p.copy(name = n))
val patchAge: Person => Person = request.age.fold[Person => Person](identity)(a => p => p.copy(age = a))
...
val updatedPerson = Patch.merge(
person,
patchName,
patchAge
...
)
I'm using monocle to update deeply nested properties of person
, but even then this is manual and repetitive... and boilerplatey :(
Patch.merge
does a foldLeft
over the Seq[A => A]
, applying it to the initial A
...