Hacker News new | ask | show | jobs
by jbooth 4001 days ago
What's Scala's superior alternative to builder patterns? You can have lots of final members in a constructor in Java, too..
1 comments

State monad and/or lenses when appropriate, which is made quite pleasant to use with for comprehension's syntactic sugar.
You mind pasting an example? I typically find higher kinded types, monads etc to be more of a pain than the problems they're solving (builders & constructors not really that painful IMO), but am really trying to keep an open mind.
Sure, here's an example with lenses, taken from actual code I've written:

    (for {
      _ <- EventLenses.duid := UserDuid("12345")
      _ <- EventLenses.contexts := Seq(EventContext.NilContext)
      _ <- EventLenses.url := "http://news.ycombinator.com"
    } yield ()).run(originalEvent)
This code will take an event, set it's duid, contexts and url. If you squint hard enough it almost looks like:

    originalEvent.duid = ...
    originalEvent.contexts = ...
    originalEvent.url = ...
The thing that's cool about lenses is that they compose nicely. E.g., the contexts lens is defined as:

    val contexts: Lens[Event, Seq[EventContext]] = query >=> getterMLens("cx") >=> Lens.lensu(...)
This means that first we take the query lens, compose it with a lens that gets the "cx" parameter, then do the actual work of decoding the "cx" param.
Hey, thanks for filling in. So basically a facade over the original object only masking some fields.. yeah, not really my cup of tea personally, I'm fine with approx the same amount of code for a boring builder and/or constructor call to duplicate an object, or, if appropriate, a mutable object. But it's definitely nifty.
another great thing is it's 'replayable'. If the event is stored in an atomic reference, you can get optimistic transactional semantics by running the state monad, comparing the results to the previous by using a CAS, etc. So you have free concurrent transactional semantics from using the state monad.