4

我经常写形式的代码

(->> init
     (map ...)
     (filter ...)
     (first))

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

(transduce (comp (map ...) (filter ...)) (completing #(reduced %2)) nil init)

写作(completing #(reduced %2))而不是first我根本不喜欢。它不必要地掩盖了一项非常简单的任务。是否有更惯用的方式来执行此任务?

4

2 回答 2

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])

如果你需要这一堆,那么我可能不会创建自定义 reducer 函数,而是创建一个类似于 transduce 的函数,它以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])
于 2017-12-05T17:59:23.630 回答
0

medleyfind-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)
于 2017-12-05T01:53:15.633 回答