Hacker News new | ask | show | jobs
by runT1ME 4001 days ago
I'm not sure how familiar you are with scala if you are equating them in equal 'functional power' to Ruby and Javascript. Have you read Functional Programming in Scala? The fact that the language supports immutable records out of the box, type classes, monadic comprehension all make it much more pleasant to deal with the realities of immutable data.

You can write immutable java, but the language doesn't make it easy to at all. Look at the hilariously bad builder pattern (which is as good as it gets in Java) compared to the right way of doing things in Scala.

2 comments

Sadly I'm sceptical that the JVM can support practical and efficient use of functional structures such as monads. I hope this will change.
What's Scala's superior alternative to builder patterns? You can have lots of final members in a constructor in Java, too..
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.