Есть ли в Clojure редукционная функция, которая выполняет эквивалент `first`?

Я часто пишу код формы

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

При преобразовании этого кода в код, использующий преобразователи, я получу что-то вроде

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

Пишу (completing #(reduced %2)) вместо first не очень хорошо со мной сидит Это излишне затеняет очень простую задачу. Есть ли более идиоматический способ выполнения этой задачи?

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

Если вам нужна эта куча, то я бы, вероятно, НЕ создавал пользовательскую функцию редуктора, а вместо этого функцию, аналогичную преобразованию, которое принимает 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])

попурри find-first с преобразователем арности и 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)
Другие вопросы по тегам