clojure 2026-04-17

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!

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?

👆 2

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

(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

➕ 3

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

👍 1

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

👍 1

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

👍 1

; 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 %)))

🙌 1