Reputation: 434
In Java I can do this
list.stream().peek(System.out::println).filter(i -> i >= 0).findFirst();
This will find the first positive number in a list, printing all numbers since the begining until the first positive number.
I need something similar in Clojure, but I can't find a equivalent for peek. peek does something different in Clojure. I need to create a side effect without consuming the sequence, intermediary. Just as elements pass through, they should be passed to a function. I could implement it myself, but I don't want to reinvent something existing. Seems like basic functionality, I was unable to find the right function to call).
Upvotes: 1
Views: 177
Reputation: 4816
Just use map
in combination with doto
and transducers to have it do a side effect and otherwise be a passthrough:
(into []
(comp
(map #(doto % println))
(filter pos?)
(take 1))
[-1 -2 -3 4 5])
Or for what you said in your comment you can use do
for example:
(->>
(repeatedly #(rand-nth [1 nil nil]))
(into []
(comp
(map #(do (when (nil? %) (Thread/sleep 1000)) %))
(remove nil?)
(take 1)))
first)
I'm using transducers, because lazy sequences are not guaranteed to be one at a time, due to chunking, and special care is needed if you want to avoid that, so it's just much better and easier in a case where you want to mix in side-effects inside a data transformation pipeline to use transducers instead.
Upvotes: 1
Reputation: 29984
If you study the Clojure CheatSheet, you can find the function split-with
which does pretty much what you want:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(dotest
(let [[dropped kept] (split-with #(neg? %) (range -10 10))]
(is= dropped [-10 -9 -8 -7 -6 -5 -4 -3 -2 -1])
(is= kept [0 1 2 3 4 5 6 7 8 9])
(is= 0 (first kept))))
If you need something in the future and can't find a built-in function that works, you can always write simple loops (or "recursion") using loop/recur
.
Please also see this list of documentation.
Upvotes: 0