Как я узнал о преобразователях в Clojure, мне внезапно показалось, что они напомнили мне: Java 8 потоков!
Clojure:
(def xf
  (comp
    (filter odd?)
    (map inc)
    (take 5)))
(println
  (transduce xf + (range 100)))  ; => 30
(println
  (into [] xf (range 100)))      ; => [2 4 6 8 10]
Java:
// Purposely using Function and boxed primitive streams (instead of
// UnaryOperator<LongStream>) in order to keep it general.
Function<Stream<Long>, Stream<Long>> xf =
        s -> s.filter(n -> n % 2L == 1L)
                .map(n -> n + 1L)
                .limit(5L);
System.out.println(
        xf.apply(LongStream.range(0L, 100L).boxed())
                .reduce(0L, Math::addExact));    // => 30
System.out.println(
        xf.apply(LongStream.range(0L, 100L).boxed())
                .collect(Collectors.toList()));  // => [2, 4, 6, 8, 10]
Помимо различий в статическом/динамическом типировании, они кажутся мне очень похожими по назначению и использованию.
Является ли аналогия с преобразованиями потоков Java разумным образом думать о преобразователях? Если нет, то как это порочит, или как эти два отличаются по понятию (не говоря уже о реализации)?
