【问题标题】:How to convert this map/flatMap into a for comprehension in Clojure?如何将此地图/平面地图转换为 Clojure 中的理解?
【发布时间】:2014-10-28 14:13:01
【问题描述】:

给定this Scala code

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

然后翻译成这个以便理解:

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

我的问题是如何在 Clojure 中将此 map/flatMap 转换为 for comprehension?

假设:

  • 如果可能的话,我想使用惯用的 Clojure(即mapcat)来表示这个而不是algo.monads / fluokitten 库。但是,如果这是最好的方法(我愿意学习),那就使用它。

【问题讨论】:

    标签: scala clojure monads for-comprehension flatmap


    【解决方案1】:

    你可能不会在 Clojure 中使用 Option,但如果对象在集合中,这样的东西应该可以工作:

    (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)))
      ;=> '()
    

    【讨论】:

    • 好的 - 所以如果我们想使用Option - 那么我们回到algo.monads onclojure.com/2009/03/05/… - 对吗?
    • @hawkeye,要使用for,您需要将对象包装在序列中,如果这不行,那么您可能需要使用algo.monads(或自己滚动)。
    • 好的——你是说for-comprehension基本上是一个for循环,顶部有一个let-block?
    • @hawkeye,不是真的没有。正如您从我在每个步骤中的示例中看到的那样,它会“展平”集合,并且如果任何集合为空,也会停止评估。使用for+let,您需要手动映射集合并将它们展平。
    • @hawkeye (1) 我不会说 Scala,但看起来 Option[Foo] 表示 maybeFoo 可能是一个对象,也可能什么都不是。在 Clojure 中,我们无缘无故地使用 nil,它按预期排序 (for [x nil] x) ;=&gt; ())。 (2) for comprehension 就像 Haskell 中 list monad 的 do 表示法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-13
    相关资源
    最近更新 更多