This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-05-21
Channels
- # announcements (4)
- # beginners (47)
- # cider (7)
- # clj-kondo (9)
- # cljs-dev (16)
- # clojure (8)
- # clojure-dev (33)
- # clojure-europe (39)
- # clojure-germany (2)
- # clojure-my (1)
- # clojure-nl (1)
- # clojure-norway (18)
- # clojure-uk (6)
- # clojuredesign-podcast (8)
- # clojurescript (12)
- # cursive (9)
- # datomic (24)
- # docker (3)
- # fulcro (23)
- # hoplon (7)
- # hyperfiddle (2)
- # java (5)
- # jvm (3)
- # leiningen (9)
- # lsp (6)
- # off-topic (75)
- # pathom (17)
- # polylith (21)
- # reitit (1)
- # rewrite-clj (11)
- # scittle (2)
- # shadow-cljs (57)
- # uncomplicate (6)
- # yamlscript (27)
Hi! I'm still in the process of learning clojure, using euler problems so far.
The image represents my progress so far.
I'm doing euler https://projecteuler.net/problem=12, and in order to do that, I thought that would be a good idea to finally get better understanding of lazy-seq
I get that I can probably generate them by simply using reductions
with something like
(defn triangular-numbers (reductions + (iterate inc 1)))
However, i'm trying to get a hang of lazy-seq
The following seems to work, but I feel I have it more complicated that it should be.
(defn triangular-numbers
([] (triangular-numbers 1 0))
([curr prev] (cons (+ curr prev)
(lazy-seq (triangular-numbers (inc curr) (+ curr prev))))))
a bit more satisfied with my next version:
(def triangular-numbers
((fn t-n [curr previous]
(let [next (+ curr previous)]
(lazy-seq (cons next (t-n (inc curr) next))))) 1 0))
In that situation, I might letfn the function and then call it because sometimes the double parens read a little strange (to me). But that's just my preference. I might also name the variables a bit differently to distinguish between the 'counter' and the 'total'. In general, this looks to line up nicely with the recipe at <https://clojure.org/reference/lazy>.

I guess I can rename next to total, but the rest is just the previous and current value, as I didn't find a way to avoid that, I feel those are named ok.
so you meant something more like this?
(def triangular-numbers
(letfn [(t-n [curr previous]
(let [total (+ curr previous)]
(lazy-seq (cons total (t-n (inc curr) total)))))]
(t-n 1 0)))
(def triangular-numbers
(letfn [(triangular-n [counter previousTotal]
(let [total (+ counter previousTotal)]
(lazy-seq (cons total (triangular-n (inc counter) total)))))]
(triangular-n 1 0)))
I find the extra letfn and fn bindings unnecessary. I think your original solution with a simple let works well.
(defn triangular
([] (triangular 1 0))
([curr prev]
(let [n (+ curr prev)]
(lazy-seq (cons n (triangular (inc curr) n))))))

For one, the letfn obfuscates matters and hides the recursive nature of the call.
Is there a reason you abandoned the defn
and went with the def
?
If you are worried about having a signature that allows consumers to invoke triangular with arguments and you only want to expose the sequence, then you’re better off making this private and declaring a public facing var with the sequence defined.
well I was worried about few things: • def vs. defn was for the caller to not have it to look like (take 5 (triangular-numbers)) vs (take 5 triangular-numbers)... which i tend to prefer (for that use case) • then yes I was worried about invoker able to call it with arguments when i didn't want.
though considering it's all just personal euler project to practice, there's no actual worry. and I do like the use of private (I guess using defn-
with a public var which both makes everything cleaner and does fit my first aesthetic preference on point one)
and definitely dropping the -number
is worth it, I do like how the code you posted looks like.
I guess my main worry initially was rather or not I was using lazy-seq
correctly as it seemed that having access to the previous value to calculate the next one would be so common that I was thinking I was doing something wrong with having a two-args signature...
Hello, I am trying to implement authentication/authorization in Clojure backend project. Seems like there's a library called "Buddy" which has been popular yet not maintained anymore, but I also heard that many Clojure libraries reach their own maturity, and doesn't need to be updated anymore. I wonder if that's the case for Buddy also - or are there any better alternatives for implementing Auth?
You're most welcome. Seriously, it's a great library and you won't have issues with it 🙂 It's tried and tested.
Hi, how would I go about taking the first item, dropping n items, and then taking n items from a lazy seq?
i.e. given the seq ~[1 2 3 4 5 6 7 8]~ (1 2 3 4 5 6 7 8)
I want to take 1
drop 2
take 2
the result being ~[1 4 5]~ (1 4 5)
I am parsing a csv file and want the header, and then want to skip n rows and take n rows…
(->> (csv/read-csv reader)
(drop 50000)
(take 100)
(csv/write-csv writer))))
this works except I don’t have the header
sorry bad example, it is a seq i am actually parsing
Thanks ill try that
except you need to drop more than 2, because you are dropping all the parts of x you don't want, which still includes the parts included in the first take
yea i get where you are going with that
i’m guessing ill have to wrap it in a fn
(->> (csv/read-csv reader)
(#(concat (take1 %) (take 2 (drop 2 %)))
(csv/write-csv writer))))
Thanks @U0NCTKEV8 that worked
another option that does more or less the same thing, but might read a little bit more nicely in this particular scenario, would be destructuring to get the first (header) row:
(let [[header & rows] (csv/read-csv some-csv)]
(concat [header] (take 5 (drop 2 rows))))
I have a lazy seq where each element takes a while to evaluate, e.g. a http request, here simulated with sleep:
(->> (for [x (range 50)]
(do (Thread/sleep 200)
(println "done with" x)
x))
(run! println))
Running this, as expected prints "done with ..." every second, but the println in the last line is not executed until 32 elements have been realized, so 32 lines are printed after 32*0.2 seconds, then again theres' a wait time and the remaining lines get printed again in a chunk. Why is that? does run/reduce realize ahead?And the followup question is, can I somehow steer that behavior to get "ticking" output?
lazy-seqs, despite the name, are based understood as "non-strict" seqs, they don't make guarantees about how lazy they are
there is an optimization that some seqs (like the ones produced by range) have where they produce laziness in chunks (of size 32)
many lazy seq operations (map, filter, for, etc) try to be transparent to chunking, in that if the input is chunked the output is chunked
My general advice is that if you care about when things happen, don't use lazy sequences. There are plenty of tools for specifying what operations should happen separately from when they should happen.
my recommendation would be something like (run! println (eduction (map (fn [x] ...)) (range 50)))
(basically don't use lazy seqs for this kind of thing)
Ok thanks! Will have a look at options.
Ya, you should think of them more as batched. But even then, when will one or two batch get realized can be hard to determine, as some functions can peek a bit further and cause another chunk to realize. For now batches are normally 32 elements long. Transducers are a pretty good replacement for when timing matters.