I'm very new to Scala and I'm still trying to get used to the syntax and style, so this is probably a very simple question.
I'm working with a codebase where there are lots of case classes populated with Options like so:
case class Person(
pants: Option[Pants]
)
case class Pants(
pocket: Option[Pocket]
)
case class Pocket(
cash: Option[Cash]
)
case class Cash(
value: String = "zilch"
)
In the example above, how would you go about returning how much money is in a Person
's Pants
Pocket
, if they are indeed wearing pants... with pockets, and if they have any money at all?
Scalaz 7 has changed a little so here is another example:
object PartialLensExample extends App {
import scalaz._
import Lens._
import PLens._
case class Bar(blub: Option[String])
case class Foo(bar: Option[Bar])
// normal lenses for getting and setting values
val fooBarL: Foo @> Option[Bar] = lensg(foo ⇒ bar ⇒ foo.copy(bar = bar), _.bar)
val barBlubL: Bar @> Option[String] = lensg(bar ⇒ blub ⇒ bar.copy(blub = blub), _.blub)
// compose the above as 'Partial Lenses', >=> is just an alias for 'andThen'
val fooBarBlubL: Foo @?> String = fooBarL.partial >=> somePLens >=> barBlubL.partial >=> somePLens
// try it
val foo = Foo(Some(Bar(Some("Hi"))))
println(fooBarBlubL.get(foo)) // Some(Hi)
println(fooBarBlubL.set(foo, "Bye")) //Foo(Some(Bar(Some(Bye))))
// setting values
val foo2 = Foo(None)
println(fooBarL.set(foo2, Some(Bar(None)))) // Foo(Some(Bar(None)))
}
A great time for for-comprehensions:
val someCash: Option[Cash] =
for( pants <- somePerson.pants;
pocket <- pants.pocket;
cash <- pocket.cash ) yield cash
Equivalently you can write the following, for which the first code is syntactic sugar (ignoring some subtleties):
val someCash: Option[Cash] =
somePerson.pants.flatMap(_.pocket.flatMap(_.cash))
(I'm not totally sure if you can write the last expression using the _
wildcards, as I did).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With