But let's step up the game a bit. Let's produce a sequence of the form [true false false true true true false false false false ...] of exact length 1000.
(take 1000 (mapcat (fn [i] (repeat i (odd? i))) (range)))But let's step up the game a bit. Let's produce a sequence of the form [true false false true true true false false false false ...] of exact length 1000.
(take 1000 (mapcat (fn [i] (repeat i (odd? i))) (range))) IntStream.iterate(0, i -> i + 1)
.mapToObj( i -> Collections.nCopies(i, i % 2 == 0) )
.flatMap(Collection::stream)
.limit(1000)
Generate an infinite series of incrementing numbers, starting from 0, map each to a stream of boolean indicating true/false, flatten that stream of streams, then limit the output.Yeah, I'd still argue that the clojure stream api is more readable though ;).
(->> (range)
(map #(repeat % (odd? %)))
(apply concat)
(take 1000)
The thing is that these additions slowly creep into java, which is great. But you still have to wait for the mercy of the language designers.Clojure is so flexible that it is possible to bring these things in as libraries, resulting in a very lightweight and stable core, and a very rapidly evolving ecosystem.
Also the persistent data-structures of Clojure make life so much easier. It's basically a language build around persistent maps and arrays.
When programming in Java (which I did for 14 years), I always thought about the little machines I was making and how they interacted. In Clojure, I'm thinking about what shape the data should be and what stack of stencils and folds (as a visual metaphor) I need to get it into that shape.
That is to say, Java is object-oriented, Clojure is data-oriented. So take data-orientation and add easy-mode concurrency and you have something wonderful.
take(10, i -> range(0, i)
.mapToObj(j -> odd(i))
.collect(joining(" ")))
.collect(joining(" "));
For reference, odd and take will look like this: private static String odd(int i) {
return Boolean.toString(i % 2 != 0);
}
private static <T> Stream<T> take(int n, Function<Integer, T> f) {
return Stream.iterate(1, i -> ++i).map(f).limit(n);
} IntStream.range(0, 100).filter(::even);To compare it with what your code produces.
[true false false true true true false false false false ...]
[true false true false true false true false true false ...]