在Clojure中是否有一个与第一个相同的缩减函数?

时间:2017-12-05 00:12:01

标签: clojure mapreduce transducer

我经常编写

形式的代码
(->> init
     (map ...)
     (filter ...)
     (first))

当将其转换为使用传感器的代码时,我最终会得到像

这样的东西
(transduce (comp (map ...) (filter ...)) (completing #(reduced %2)) nil init)

(completing #(reduced %2))代替first根本不适合我。它毫无疑问地模糊了一项非常直接的任务。是否有更惯用的方式来执行此任务?

2 个答案:

答案 0 :(得分:2)

我个人会使用自定义缩减功能的方法,但这里有一些选择:

(let [[x] (into [] (comp (map inc) (filter even?) (take 1)) [0 1])]
    x)

使用破坏:/

或者:

(first (eduction (map inc) (filter even?) [0 1])

在这里,您可以节省为您完成的comp呼叫。虽然它不是超级懒惰。它将实现多达32个元素,因此可能会浪费。 修正了(take 1)

(first (eduction (map inc) (filter even?) (take 1) [0 1]))

总体来说,与以下相比更短,并且不太清楚:

(transduce (comp (map inc) (filter even?) (take 1)) (completing #(reduced %2)) nil [0 1])

如果你需要这一堆,那么我可能 NOT 创建一个自定义的reducer函数,而是一个类似于transform的函数,它将xform, coll作为参数并返回第一个值。它更清楚它的作用,你可以给它一个很好的文档字符串。如果您想在保留致电comp时保存,也可以使其与eduction

类似
(defn single-xf
  "Returns the first item of transducing the xforms over collection"
  {:arglists '([xform* coll])}
  [& xforms]
  (transduce (apply comp (butlast xforms)) (completing #(reduced %2)) nil (last xforms)))

示例:

(single-xf (map inc) (filter even?) [0 1])

答案 1 :(得分:0)

medley find-first有一个传感器arity,xforms有一个称为last的缩减函数。我认为两者的结合就是你所追求的。

(ns foo.bar
  (:require
   [medley.core :as medley]
   [net.cgrand.xforms.rfs :as rfs]))

(transduce (comp (map ,,,) (medley/find-first ,,,)) rfs/last init)