Search code examples
scalaclojuremonadsfor-comprehensionflatmap

How to convert this map/flatMap into a for comprehension in Clojure?


Given this Scala code:

def compute2(maybeFoo: Option[Foo]): Option[Int] =
  maybeFoo.flatMap { foo =>
    foo.bar.flatMap { bar =>
      bar.baz.map { baz =>
        baz.compute
      }
    }
  }  

Which is then translated to this for comprehension:

def compute2(maybeFoo: Option[Foo]): Option[Int] =
  for {
    foo <- maybeFoo
    bar <- foo.bar
    baz <- bar.baz
  } yield baz.compute

My question is How to convert this map/flatMap into a for comprehension in Clojure?

Assumptions:

  • If possible I'd like to use idiomatic Clojure (ie mapcat) to represent this rather than the algo.monads / fluokitten libraries. But if that is the best way to do it (I'm open to learning) then use that.

Solution

  • You probably wouldn't use Option in Clojure, but if the objects are inside collections something like this should work:

    (let [maybe-foo [{:bar [{:baz [(fn [] 42)]}]}]]
      (for [foo maybe-foo
            bar (:bar foo)
            baz (:baz bar)]
        (baz)))
     ;=> '(42)
    
    (let [maybe-foo [{:bar nil}]]
      (for [foo maybe-foo
            bar (:bar foo)
            baz (:baz bar)]
        (baz)))
    ;=> '()
    
    (let [maybe-foo nil]
      (for [foo maybe-foo
            bar (:bar foo)
            baz (:baz bar)]
        (baz)))
      ;=> '()