Setting nested Options to Some(value)
Hi,
Given a nested chain of Options, is there a way to coerce the most inner one to Some?
The current operator .each allows traversing Options, but acts like map:
import com.softwaremill.quicklens._
case class C(d: Option[Int])
case class B(c: Option[C])
case class A(b: Option[B])
val a = A(b = None)
a.modify(_.b.each.c.each.d.each).setTo(3) // res0: A = A(None)
(the result is A(None), but how can we achieve a A(Some(B(Some(C(Some(3))))))?)
It could be useful if there were some operator (say, all) which can act as follows:
a.modify(_.b.all.c.all.d.all).setTo(3) // res0: A = A(Some(B(Some(C(Some(3))))))
I'm afraid this is very option-chain-specific. Firstly, you wouldn't be able to use .modify, as there need not be a value. Secondly, if e.g. B had any other fields, there's nowhere to get their values from.
What about a variation of at(idx: Int) which doesn't throw IndexOutOfBoundsException, and instead enlarges the sequence so accommodate the new index? Such a method could also be adapted to Options if we look at them as sequences if length 1.
But what would you put in the indicies in between? Also, how would you initialize an "empty" object which would be added to the sequence?
Maybe a type class Zeroable[A] with default implementations for all the primitives?
A completely alternative solution would be a withHead[A](a: A) which can work for all sequences (including Option, Either, etc.)
Maybe Zeroable would work ... but I have the feeling that this takes the .each syntax a bit too far. Wouldn't, in such situations, just writing code in .setTo with the appropriate new instance creation logic be sufficient?
Yeah, on a second thought, there's no much difference between .setTo and my suggestion.
I guess you're right :)