quicklens
quicklens copied to clipboard
The `focus` (or `via`) path operator
This would allow supporting arbitrary lens.
trait Lens[A, B] {
def modify(a: A, f: B => B): A
}
object EnglishVovels extends Lens[String, Char] {
def modify(string: String, f: Char => Char) = string map {
case v @ ('A' | 'E' | 'I' | 'O' | 'U' | 'a' | 'e' | 'i' | 'o' | 'u') => f(v)
case x => x
}
}
person.modify(_.name.focus(EnglishVovels)).using(_.toUpperCase)
What do you think?
It's not immediately clear to me how that would work (sorry for being slow :) ) - what would be an example result and what would be the signature of focus?
It would work exactly like each or at. In fact they can be rewritten as focus(Each) and Focus(At(3)) respectively, but I don’t think this is a good idea. The signature will be:
implicit class QuicklensFocus[A](val a: A) extends AnyVal {
@compileTimeOnly
def focus[B](lens: Lens[A, B]): B = sys.error("")
}
Expanded example:
val person = Person(
name = "john",
address = Address(
street = "green street"
)
)
val modified = person
.modifyAll(_.name.focus(EnglishVovels), _.address.street.focus(EnglishVovels))
.using(_.toUpperCase)
modified shouldEqual Person(
name = "jOhn",
address = Address(
street = "grEEn strEEt"
)
)
Not seen here, but you can continue traversing the path after a call to focus, just like with each.
Thanks! So this would be kind of filtering the "collection" on which focus is called + mapping to some value, which can be then traversed further, correct?
Yes, the idea is to be able to pass an arbitrary lens to focus. Another example is creating a lens that somehow modifies the scheme in a java.net.URI, even though it’s not a case class.
This sounds good! Just would need good docs - or rather examples. The two examples (with person and URI) would be great to have in the docs