Clojure转换器与Java中流的中间操作的概念相同吗?

Clojure转换器与Java中流的中间操作的概念相同吗?,java,clojure,java-8,java-stream,transducer,Java,Clojure,Java 8,Java Stream,Transducer,当我在Clojure学习传感器时,我突然想到了他们让我想起的东西:Java8流 Clojure: (def xf (公司) (过滤奇数?) (地图公司) (举5个例子) (println (传感器xf+(范围100));=>30 (println (进入[]xf(范围100));=>[2 4 6 8 10] 爪哇: //故意使用函数和装箱的基本流(而不是 //一元运算符)以保持其通用性。 函数xf= s->s.过滤器(n->n%2L==1L) .地图(n->n+1L) .限值(5L); S

当我在Clojure学习传感器时,我突然想到了他们让我想起的东西:Java8流

Clojure:

(def xf
(公司)
(过滤奇数?)
(地图公司)
(举5个例子)
(println
(传感器xf+(范围100));=>30
(println
(进入[]xf(范围100));=>[2 4 6 8 10]
爪哇:

//故意使用函数和装箱的基本流(而不是
//一元运算符)以保持其通用性。
函数xf=
s->s.过滤器(n->n%2L==1L)
.地图(n->n+1L)
.限值(5L);
System.out.println(
xf.apply(LongStream.range(0L,100L).boxed())
.reduce(0升,数学::加法器));//=>30
System.out.println(
xf.apply(LongStream.range(0L,100L).boxed())
.collect(Collectors.toList());//=>[2, 4, 6, 8, 10]
除了静态/动态类型的不同之外,它们在用途和用法上似乎与我非常相似


与Java流的转换进行类比是否是考虑转换器的合理方式?如果没有,它有什么缺陷,或者两者在概念上有什么不同(更不用说实现了)?

主要的区别是,对于流,动词集(操作)在某种程度上是关闭的,而对于转换器是开放的:例如,尝试在流上实现
分区
,感觉有点像第二流:

import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;

public class StreamUtils {
    static <T> Stream<T> delay(final Supplier<Stream<T>> thunk) {
        return Stream.of((Object) null).flatMap(x -> thunk.get());
    }

    static class Partitioner<T> implements Function<T, Stream<Stream<T>>> {
        final Function<T, ?> f;

        Object prev;
        Builder<T> sb;

        public Partitioner(Function<T, ?> f) {
            this.f = f;
        }

        public Stream<Stream<T>> apply(T t) {
            Object tag = f.apply(t);
            if (sb != null && prev.equals(tag)) {
                sb.accept(t);
                return Stream.empty();
            }
            Stream<Stream<T>> partition = sb == null ? Stream.empty() : Stream.of(sb.build());
            sb = Stream.builder();
            sb.accept(t);
            prev = tag;
            return partition;
        }

        Stream<Stream<T>> flush() {
            return sb == null ? Stream.empty() : Stream.of(sb.build());
        }
    }

    static <T> Stream<Stream<T>> partitionBy(Stream<T> in, Function<T, ?> f) {
        Partitioner<T> partitioner = new Partitioner<>(f);
        return Stream.concat(in.flatMap(partitioner), delay(() -> partitioner.flush()));
    }
}

我看到的另一个重要区别是Clojure传感器是可组合的。我经常遇到这样的情况,即我的流管道比您的示例中要长一点,在您的示例中,只有一些中间步骤可以在其他地方重复使用,例如:

someStream
.map(…)
.filter(…)

.map(…)//在我未经训练的眼里,似乎是这样。但他们对传感器的评价如此之高,也许还有别的吗?:)语义上的相似性比比皆是!“先生,我可以再多说几句吗?”阿瑟乌尔费尔德说了更多的话,不确定是否更好:)确实更好!它表明,只有在很少或没有还原上下文的平凡情况下,它们才是相同的。我怀疑这就是glts所要求的。至少似乎有一个(未维护的?)Java库朝着这个方向发展:
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.Stream.Builder;

import clojure.lang.AFn;
import clojure.lang.IFn;
import clojure.lang.Reduced;

public class StreamUtils {
    static <T> Stream<T> delay(final Supplier<Stream<T>> thunk) {
        return Stream.of((Object) null).flatMap(x -> thunk.get());
    }

    static class Transducer implements Function {
        IFn rf;

        public Transducer(IFn xf) {
            rf = (IFn) xf.invoke(new AFn() {
                public Object invoke(Object acc) {
                    return acc;
                }

                public Object invoke(Object acc, Object item) {
                    ((Builder<Object>) acc).accept(item);
                    return acc;
                }
            });
        }

        public Stream<?> apply(Object t) {
            if (rf == null) return Stream.empty();
            Object ret = rf.invoke(Stream.builder(), t);
            if (ret instanceof Reduced) {
                Reduced red = (Reduced) ret;
                Builder<?> sb = (Builder<?>) red.deref();
                return Stream.concat(sb.build(), flush());
            }
            return ((Builder<?>) ret).build();
        }

        Stream<?> flush() {
            if (rf == null) return Stream.empty();
            Builder<?> sb = (Builder<?>) rf.invoke(Stream.builder());
            rf = null;
            return sb.build();
        }
    }

    static <T> Stream<?> withTransducer(Stream<T> in, IFn xf) {
        Transducer transducer = new Transducer(xf);
        return Stream.concat(in.flatMap(transducer), delay(() -> transducer.flush()));
    }
}