This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

## 2023-09-01

## Channels

- # aleph (2)
- # announcements (3)
- # architecture (9)
- # babashka (56)
- # beginners (18)
- # calva (7)
- # catalyst (16)
- # cider (18)
- # cljfx (3)
- # cljs-dev (23)
- # clojure-europe (11)
- # clojure-hungary (1)
- # clojure-nl (2)
- # clojure-norway (24)
- # clojure-sweden (2)
- # clojurescript (37)
- # code-reviews (47)
- # datalog (3)
- # datomic (8)
- # emacs (11)
- # events (2)
- # graalvm (7)
- # gratitude (1)
- # hyperfiddle (12)
- # java (1)
- # jvm (46)
- # kaocha (3)
- # lsp (3)
- # malli (4)
- # matcher-combinators (1)
- # music (1)
- # nbb (1)
- # nrepl (4)
- # releases (1)
- # sci (15)
- # shadow-cljs (21)
- # slack-help (21)
- # tools-deps (17)

Does clojure hold onto the beginning portion of a seq when using something like `nth`

?
e.g. `(fn [n] (nth (iterate #(conj % 1) []) n))`

.
`iterate`

would generate a lazy seq `[[1] [1 1] [1 1 1] ...]`

, to then be fed to `nth`

If the answer is yes, then the space complexity would be n^2. Is this correct?

I'm like 95% sure the short answer is 'no' - `nth`

shouldn't hold onto the head - iterate returns a seq that isn't fully realize, and then nth, way down in the guts of RT.java, has a for loop that iterates through the `next`

s of that seq until it hits the correct index

Say I want to iterate a function until some condition about the results is met. For example, I have a function to roll an n-sided die and I want to do it over and over again until I see that I've rolled a particular number three times (total, not necessarily in a row).
I know there's `iterate`

which I could use to call my rolling function over and over, and it could return the current sequence of rolls. I could then `take-while`

the sequence doesn't have three of the same number.
This seems a bit awkward because every iteration, the predicate has to test a larger and larger sequence for the end condition. If I'm rolling a D20, that's potentially a lot of linear traversals on a continuously larger data structure.
Is there any nice, idiomatic way to do something like this (a stateful terminal condition), or is my best bet just to write my own `loop/recur`

?

loop/recur is fine and sometimes you will notice that you have reinvented a pattern. But "reductions" also comes to mind!

could use `halt-when`

with transducers

but with state, prob loop/reduce is clearest

depending on some context (namely whether the order of the sequence is important), it might be faster to track in a map of rolls to how many times it has rolled (still in loop recur, but rather than re-counting each time)

I guess both `halt-when`

and `reductions`

would be similar to what I described above, right? There would still be a predicate involved that would take a sequence of rolls and check it for three of a kind.
I suppose I could maintain both the map and the sequence together in a data structure as I iterate so that I could `halt-when`

one of the map values is 3. Does that make sense to do?

I think keeping the running map makes sense - I guess one could weakly analogize this to how clojure collections are counted - they keep track of their count so it's constant-time instead of having to count the elements when the count is asked for

Well if you care about perf, then it's typically useful to state concrete assumptions. If you know it's going to be a d20, you know you can allocate an array of 20 elements with 0's and then inc the appropriate index. There are probably much smarter solutions too.

this is just a 5-minute hack job, so it's not particularly well-factored or anything, but:

```
(defn dice-rolls-until-reps [sides reps]
(let [next-roll (fn [[seq acc]]
(let [this-roll (inc (rand-int sides))]
[(conj seq this-roll) (update acc this-roll (fnil inc 0))]))
rolls (iterate next-roll [[] {}])]
(ffirst (filter (comp #(some #{reps} %) vals second) rolls))))
(dice-rolls-until-reps 6 3)
;; [1 1 2 4 1]
```

Cool, thanks. Is it a fairly common pattern to build up a data structure of "extra" stuff during an iteration or reduction, and then unpack what you need at the end?

Your problem is nerd sniping me a bit. If it's really d20's there's perhaps a clever way of doing this since you have a finite number of results. They are permutations of these:

```
(1 1 1)
...
(1 1 2 2 3 3 ... 20 20 20)
...
(20 20 19 19 18 18 ... 1 1 1)
```

Now I'm not good/quick enough at math to know how many there are. But if it's a reasonable number you might just be able to just generate 1 random number and then "pick" one of the permutations so to speak.if that sounds useful/interesting to you, you might want to look at this library here: https://github.com/clojure/math.combinatorics

The problem isn't dice; that was just the simplest example I could come up with that had roughly the same shape as what I'm trying to do. It paid off a bit though: that's a very interesting idea, and I'll take a look at the library too, if only to have it in my toolbox for the future. So effectively, you're suggesting a potential solution where, if you know you have a finite (and I guess ideally not crazy huge) set of possibilities before you hit the terminal condition, you could replace iterative generation with a random selection of one of the possibilities.