Is it possible to require a test or "dev" namespace from a library dep in a different project?
the only thing that matters is the classpath. You cannot add aliases to dependencies (as of yet. i think this is a requested feature with some interest to implement)
so if a dep includes the dev or test namespace in its default classpath (`:src` entry of its deps.edn without aliases) you should be able to load it
that's kinda what I figured, but wanted to confirm - thanks!
here's the relevant Ask thread for anyone else interested: https://ask.clojure.org/index.php/7843/allow-specifying-aliases-coordinates-that-point-projects
i was trying to find it and wasn’t. thanks!
I’ve got code like his:
(->> [{:n 1} {:n 2} {:n 3}]
(map :n)
(mapcat #(do (println %)
[%]))
(m/find-first #(= 2 %)))
there’s no easy way to make this lazy (i.e. not print 3) is there?I’m curious about the actual problem you’re trying to solve. Like, I get that we’re discussing lazyness here, but you’re taking a list, doing some stuff with it, somethings are cheap, like the map operation, somethings are expensive like the mapcat operation. Is the mapcat thing sideffecty? can it be done cheaper? Can you do something to the input such that you don’t need the mapcat?
it is lazy
well it’s chunked
so it loads like 30 elements right off the bat
yes. and there you run into issues that trying to control the amount of laziness with lazy sequences is a bad fit
well I just want it to be fully lazy
the mapcat operation is expensive
that’s a fine request. i’d use a transducer pipeline to control the exact amount of realization
(transduce (mapcat #(do (println %)
[%]))
(completing #(when (= 2 %2) (reduced %2)))
nil
(range 1000))not very pretty
not pretty but presumably controls the amount of execution deterministically right?
(first (for [n (range 1000)
x (do (println n)
[n])
:when (= 2 x)]
x))but lazy sequences make some generalized tradeoffs. one of which is to not do laziness at the individual level but in chunks
this is fully lazy
but if you change it to
(take 3 (for [n (range 1000)
x (do (println n)
[n])
:when (= 2 x)]
x))
is it still “fully” lazy?again. up to you to fight this demon if you want. But lazy sequences aren’t the right tool for what you are wanting to maintain i think
in a way, yes, it would resolve just as much as needed for 3 items, which is everything in this case as there are not 3 times 2
Kinda code-golfey because of that {}, but you can use (fn [_ x] x) just fine. Probably even better.
(->> (range 1000)
(transduce (comp (mapcat #(do (println %)
[%]))
(m/find-first #(= % 2)))
(completing {})
nil))so that ’s ully lazy
Oh, wait - my code doesn't return anything. There, fixed it.
this prints everything for me
yeah because it needs to resolve it all to look for more (= 2 x)
which there isn’t any
it returns (2) and finds it
certainly (range 50) has the 2 element
yeah but it looks for 3
oh sorry yeah the take 3
so it traverses all
yeah got that one backwards. sorry
then there’s this:
(letfn [(res [[n & more]]
(println n)
(concat [n]
(when more (lazy-seq (res more)))))]
(m/find-first #(= % 2) (res (range 1000))))also rather verbose
but you can stack laziness however you want
isn't there a way to turn a lazy chunked seq into a 1-by-1 lazy seq? i vaguely remember someone posting that
yeah that was what I was hoping for
there are a few unchunk macros floating around
look at us
(defn seq1 [s]
(lazy-seq
(when-let [[x] (seq s)]
(cons x (seq1 (rest s)))))) just don’t do anything to that seq like map over it, etc. it’s fragile. up to you. one day you edit some code somewhere else and performance tanks because you’re relying on laziness behavior that is not part of a contract. i’ll take explicit control flow over aesthetics in this case. But up to you
I would assume that (first s) call would run the whole chink
ok rewrote it as nested (some (m/find-first)) so it’s explicit
huh, maybe chunking has changed how seq1 or unchunk works because i'm still seeing chunking behavior when i try it out
so instead of:
(->> [{:n 1} {:n 2} {:n 3}]
(map :n)
(mapcat #(do (println %)
[%]))
(m/find-first #(= 2 %)))
i made
(->> [{:n 1} {:n 2} {:n 3}]
(map :n)
(some #(m/find-first (fn [n] (= 2 n))
(do (println %) [%]))))
possible nrepl’s repl printer changes things too. i’m using a socket repl without nrepl
unkchunking stuff like seq1 need to be applied before your other operations
I don’t see how seq1 or unchunk could ever work. You are calling first on underlying seq, there’s nothing stoping that seq from resolving 32 items
but yeah you can put it around other input sequences as a guard and that would work
not after the lazy stack of map is created
e.g. (first (seq1 (map expensive-fn chunked-seq))) you will still get chunking in how that map seq is realized before seq1 unchunks it
; doesn't work
(take 3 (unchunk (map (fn [i] (print ".") (inc i)) (range 1000))))
; works
(take 3 (map (fn [i] (print ".") (inc i)) (unchunk (range 1000))))you can also get seqs that are a mix of chunked and a not via concat (or even build them that way using lazy-seq, but I have never seen that done)
@roklenarcic Reducibles is the way to go. Just generalize the reduce-based find-when and it will stop being too complicated or ugly.
(defn find-when [pred reducible]
(reduce #(when (pred %2) (reduced %2)) nil reducible))
(->> [{:n 1} {:n 2} {:n 3}]
(eduction (comp (map :n)
(mapcat #(do (println %)
[%]))))
(find-when #(= 2 %)))