beginners

Colton Goates 2025-09-21T11:34:43.607889Z

Functions from the seq library turn my vectors into seqs, which causes me problems. What should I do? Do I just get used to calling vec or into [] everytime I want to use a seq function? I know there is mapv, but most of these functions don't have a "v" variant. Is there something I'm missing?

p-himik 2025-09-21T11:58:33.336939Z

> Do I just get used to calling vec or into [] everytime I want to use a seq function? No. Only every time you need a vector. Or every time you need a non-lazy result and want to create it with transducers.

šŸ‘ 1
teodorlu 2025-09-21T12:32:08.740639Z

If you want / need a specific type of sequence, consider transducers. They give you that control, and spares you the cost of allocating intermediate sequences. Sean Corfield's transducer into on Civitas is excellent: https://clojurecivitas.github.io/clojure/transducers/what_if.html

šŸ‘ 1
teodorlu 2025-09-21T12:33:55.416089Z

As Eugene, I normally stick to seqs when I code, converting to vectors and sets only when needed.

šŸ‘ 1
Bob B 2025-09-21T13:19:58.451979Z

And if you want to get deeper into it, perhaps you could describe the perceived problem(s). The way the question is phrased sort of implies the problems that seqs cause are intrinsically, objectively problematic, so it's possible that an analogy might be if the question were "I can't freely mutate my local bindings and that's a problem, do I have to use atoms every time?". There's probably a way to make immutable bindings less of a hurdle. Another option that's out there is specter (<https://github.com/redplanetlabs/specter>). It's quite a different approach to manipulating collections, but it mostly (always?) retains the input collection type, and some find that its style works for them.

šŸ‘ 1
p-himik 2025-09-21T13:39:06.486239Z

> As Eugene, I normally stick to seqs when I code I actually almost always use (into [] ...) because I "need" non-lazy results. :) I find it simpler, easier to reason about, easier to debug if something goes wrong. And usually it's more performant as well.

šŸ‘ 3
āž• 1
Colton Goates 2025-09-21T16:12:48.899829Z

@highpressurecarsalesm I would be open to making fuller use of seqs and I don't think there is anything wrong with them. First, I'll tell you what prompted this question. I was programming the reverse card in Uno and I accidentally wrote (update game :players reverse) instead of (update game :players #(vec (reverse %)) . Then I called

(defn current-player
  [game]
  (get-in game [:players (:i game)]))
and current-player returned null because the players vector got turned into a seq. For a simpler example, (get (seq [1 2 3]) 1) returns null. If I have a vector, there is a reason I'm using a vector, and I want to avoid accidentally turning it into a seq. But like I said, I would love to take advantage of seqs more if you have any tips

p-himik 2025-09-21T16:16:46.484289Z

A small note: instead of (vec (reverse some-vec)) you should use (vec (rseq some-vec)).

šŸ‘ 1
Colton Goates 2025-09-21T16:18:00.356889Z

@p-himik @teodorlu I haven't thought much about transducers. I'll have to look into those

liebs 2025-09-21T16:55:57.213889Z

If transducers are intimidating at first (as they are for many), you can chain together the transformations with comp and/or -> /`->>`, applying vec or into [] at the end of the pipeline

šŸ‘ 1
2025-09-21T19:38:03.652419Z

What problem are you getting?

Colton Goates 2025-09-21T19:39:52.172889Z

@didibus see my comment to Bob above. My vector got turned into a seq, then I was no longer able to access its elements using get coll i

2025-09-21T19:50:21.554119Z

Ah ya, sorry had missed that comment.

2025-09-21T19:53:22.298739Z

I'd say one thing that's not obvious. Is that you need to decide between coll functions or seq functions. And you need to be aware of that. It's a little tricky at first, but you get used to it.

šŸ‘ 1
2025-09-21T19:59:42.918209Z

Just remember that all seq functions return sequences. So if you want something else, you need to add a last step to get what you want. There's not much difference since everything is creating a new vector anyways, since it's all immutable. So it's not like you're missing out on in-place mutation.

šŸ‘ 1
Colton Goates 2025-09-21T20:17:01.899799Z

@didibus yeah, I get the idea of choosing. The trouble is that many clojure.core seq functions don't have a corresponding coll function, so I'm stuck calling vec or set etc. when I want to preserve the collection type. That's okay--in Java I had to call .toList() after a .stream() call, not much different šŸ™‚

2025-09-21T20:47:53.270109Z

Ya absolutely. I think more recent versions added a few more "v" ending variants for convenience around this. But I'd say, the idea is that you do a "pipeline of transforms" and then go back to wtv coll type you wanted if that's what you need. And the reason it's like this, is because since colls are immutable, you don't need a variant of every function specialized to inline mutation of that particular structure. So it goes:

(->> <from-coll>
     transform
     transform
     (into <type>))
As the general pattern. Transducers are type independent, like functions from "element to element". They're not really specialized to vectors, but with transducers there's no default caching, so you're forced to specify the <to-type> each time you use them like:
(into []
  (comp transform
        transform)
  <from-coll>)
And you have to use them with into or transduce otherwise they're not even going to do anything. But it's the same idea, functions that work of a kind of "iterator" are just implemented in terms of iteration, and you have to "Collect" their results into something. Seqs always collect into a singly-linked-list-like thing, which you can then transfer into something else. And transducers collect into an explicit thing you have to specify.

šŸ‘ 1
James Amberger 2025-09-22T00:34:17.397279Z

This is my favorite question I think (not that I’m anything but a novice myself).

James Amberger 2025-09-22T00:41:20.500309Z

cf. https://clojurians.slack.com/archives/C053AK3F9/p1746934158512559

James Amberger 2025-09-22T00:43:08.015369Z

And as to your prompt, > If I have a vector, there is a reason I’m using a vector, and I want to avoid accidentally turning it into a seq. what is the reason in this case?

Colton Goates 2025-09-22T03:30:19.306269Z

@james.amberger it is an interesting discussion that cuts to the heart of what Clojure is about. As for the reason, see my response to @highpressurecarsalesm earlier in this thread: https://clojurians.slack.com/archives/C053AK3F9/p1758471168899829?thread_ts=1758454483.607889&amp;cid=C053AK3F9

James Amberger 2025-09-22T11:43:43.139699Z

ok, there is a reason you are using a vector. What is it?

2025-09-22T14:38:43.154589Z

@james.amberger He's doing O(1) random access use get by index

ā˜ļø 1