I agree with what Reynold said -- there's not a big benefit in terms of
lines of code (esp. compared to using getOrElse) and I think it hurts code
readability.  One of the great things about the current Spark codebase is
that it's very accessible for newcomers -- something that would be less
true with this use of "fold".


On Thu, Dec 26, 2013 at 8:11 PM, Holden Karau <hol...@pigscanfly.ca> wrote:

> I personally with Evan in that I prefer map with getOrElse over fold with
> options (but that just my personal preference) :)
>
>
> On Thu, Dec 26, 2013 at 7:58 PM, Reynold Xin <r...@databricks.com> wrote:
>
> > I'm not strongly against Option.fold, but I find the readability getting
> > worse for the use case you brought up.  For the use case of if/else, I
> find
> > Option.fold pretty confusing because it reverses the order of Some vs
> None.
> > Also, when code gets long, the lack of an obvious boundary (the only
> > boundary is "} {") with two closures is pretty confusing.
> >
> >
> > On Thu, Dec 26, 2013 at 4:23 PM, Mark Hamstra <m...@clearstorydata.com
> > >wrote:
> >
> > > On the contrary, it is the completely natural place for the initial
> value
> > > of the accumulator, and provides the expected result of folding over an
> > > empty collection.
> > >
> > > scala> val l: List[Int] = List()
> > >
> > > l: List[Int] = List()
> > >
> > >
> > > scala> l.fold(42)(_ + _)
> > >
> > > res0: Int = 42
> > >
> > >
> > > scala> val o: Option[Int] = None
> > >
> > > o: Option[Int] = None
> > >
> > >
> > > scala> o.fold(42)(_ + 1)
> > >
> > > res1: Int = 42
> > >
> > >
> > > On Thu, Dec 26, 2013 at 5:51 PM, Evan Chan <e...@ooyala.com> wrote:
> > >
> > > > +1 for using more functional idioms in general.
> > > >
> > > > That's a pretty clever use of `fold`, but putting the default
> condition
> > > > first there makes it not as intuitive.   What about the following,
> > which
> > > > are more readable?
> > > >
> > > >     option.map { a => someFuncMakesB() }
> > > >               .getOrElse(b)
> > > >
> > > >     option.map { a => someFuncMakesB() }
> > > >               .orElse { a => otherDefaultB() }.get
> > > >
> > > >
> > > > On Thu, Dec 26, 2013 at 12:33 PM, Mark Hamstra <
> > m...@clearstorydata.com
> > > > >wrote:
> > > >
> > > > > In code added to Spark over the past several months, I'm glad to
> see
> > > more
> > > > > use of `foreach`, `for`, `map` and `flatMap` over `Option` instead
> of
> > > > > pattern matching boilerplate.  There are opportunities to push
> > `Option`
> > > > > idioms even further now that we are using Scala 2.10 in master,
> but I
> > > > want
> > > > > to discuss the issue here a little bit before committing code whose
> > > form
> > > > > may be a little unfamiliar to some Spark developers.
> > > > >
> > > > > In particular, I really like the use of `fold` with `Option` to
> > cleanly
> > > > an
> > > > > concisely express the "do something if the Option is None; do
> > something
> > > > > else with the thing contained in the Option if it is Some" code
> > > fragment.
> > > > >
> > > > > An example:
> > > > >
> > > > > Instead of...
> > > > >
> > > > > val driver = drivers.find(_.id == driverId)
> > > > > driver match {
> > > > >   case Some(d) =>
> > > > >     if (waitingDrivers.contains(d)) { waitingDrivers -= d }
> > > > >     else {
> > > > >       d.worker.foreach { w =>
> > > > >         w.actor ! KillDriver(driverId)
> > > > >       }
> > > > >     }
> > > > >     val msg = s"Kill request for $driverId submitted"
> > > > >     logInfo(msg)
> > > > >     sender ! KillDriverResponse(true, msg)
> > > > >   case None =>
> > > > >     val msg = s"Could not find running driver $driverId"
> > > > >     logWarning(msg)
> > > > >     sender ! KillDriverResponse(false, msg)
> > > > > }
> > > > >
> > > > > ...using fold we end up with...
> > > > >
> > > > > driver.fold
> > > > >   {
> > > > >     val msg = s"Could not find running driver $driverId"
> > > > >     logWarning(msg)
> > > > >     sender ! KillDriverResponse(false, msg)
> > > > >   }
> > > > >   { d =>
> > > > >     if (waitingDrivers.contains(d)) { waitingDrivers -= d }
> > > > >     else {
> > > > >       d.worker.foreach { w =>
> > > > >         w.actor ! KillDriver(driverId)
> > > > >       }
> > > > >     }
> > > > >     val msg = s"Kill request for $driverId submitted"
> > > > >     logInfo(msg)
> > > > >     sender ! KillDriverResponse(true, msg)
> > > > >   }
> > > > >
> > > > >
> > > > > So the basic pattern (and my proposed formatting standard) for
> > folding
> > > > over
> > > > > an `Option[A]` from which you need to produce a B (which may be
> Unit
> > if
> > > > > you're only interested in side effects) is:
> > > > >
> > > > > anOption.fold
> > > > >   {
> > > > >     // something that evaluates to a B if anOption = None
> > > > >   }
> > > > >   { a =>
> > > > >     // something that transforms `a` into a B if anOption = Some(a)
> > > > >   }
> > > > >
> > > > >
> > > > > Any thoughts?  Does anyone really, really hate this style of coding
> > and
> > > > > oppose its use in Spark?
> > > > >
> > > >
> > > >
> > > >
> > > > --
> > > > --
> > > > Evan Chan
> > > > Staff Engineer
> > > > e...@ooyala.com  |
> > > >
> > > > <http://www.ooyala.com/>
> > > > <http://www.facebook.com/ooyala><
> > http://www.linkedin.com/company/ooyala
> > > ><
> > > > http://www.twitter.com/ooyala>
> > > >
> > >
> >
>
>
>
> --
> Cell : 425-233-8271
>

Reply via email to