Fork me on GitHub
#beginners
<
2024-06-08
>
Rushal Verma12:06:38

Why the get works with almost every other collection (map, vector, string etc) but not with list?

(get [1 2 3 4 5] 3) => 4
(get "larry common as of today month seniority beautiful" 30) => \h
(get '(1 2 3 4 5) 3) => nil

daveliepmann12:06:20

All the others are associative. Lists are not.

daveliepmann12:06:48

hmm, hold on, that's not true of Strings

Rushal Verma12:06:49

what exactly associative means here then and why lists are not associative?

daveliepmann12:06:57

associative means that the collection represents some sort of key/value relationship, like keys/values in a map, indices to values in a vector

daveliepmann13:06:25

your original question seems answered by get's docstring, which says it operates on "associative collection, set, string, array, or ILookup instance"

Rushal Verma13:06:24

but lists also can be associative, or it’s not? like I can fetch with items from a list by indexes so they too can be associative, isn’t? (same as vector)

daveliepmann13:06:23

no. lists aren't associative (or any of the other get-supported things) — because it's not what lists are designed for. (vectors are designed to have indices)

nikolavojicic13:06:49

But you can use nth on a list.

daveliepmann13:06:56

"'nth' for seqs is a counterexample, was requested by the community, and I still think is somewhat of a mistake." –Rich https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f#why-cannot-last-be-fast-on-vector

👍 1
Rushal Verma13:06:31

> it’s not what lists are designed for. (vectors are designed to have indices) so what lists been designed for? if they aren’t almost same like vector! (sorry to stretch it further as Clojure is my first functional language and I’ve background in python so I might be making mapping in my head but want to actually understand it)

nikolavojicic13:06:18

Mostly for code.

1
jaihindhreddy13:06:36

> so what lists been designed for? if they aren’t almost same like vector! Lists are linked-lists, and they support sequential access, and not random-access using indexes (like vectors do). The literal list-syntax (i.e, parentheses) came from Lisp heritage of course.

😮 1
🙌 1
Rushal Verma13:06:07

so lists are mostly for code (is it like syntactic sugar or something?) and vectors are designed for indices, is that right?

jaihindhreddy13:06:02

> is it like syntactic sugar or something? No. They are different types:

user=> (class (list 1))
clojure.lang.PersistentList
user=> (class [1])
clojure.lang.PersistentVector

🙌 1
daveliepmann13:06:09

"Vectors are an indexed, sequential data structure." "Lists are sequential linked lists that add new elements at the head of the list" https://clojure.org/guides/learn/sequential_colls

🙌 1
Rushal Verma13:06:27

Thanks, this is what I was searching for this will help in my understanding Thanks, for the link and REPL code (I’ll use that more often from now on) 🙌

👍 1
nikolavojicic13:06:04

Operator is always in the head/first position and operands are tail/rest. Linked list is good for that.

nikolavojicic13:06:22

Also, when doing recursion.

daveliepmann13:06:02

(I was confused above about whether sets are associative — some clarification here: https://ask.clojure.org/index.php/8894/why-do-sets-not-implements-ilookup )

🙌 1
jaihindhreddy13:06:45

> No. They are different types: More correctly, a "Clojure vector" is anything that implements the Java interface clojure.lang.IPersistentVector. The aforementioned clojure.lang.PersistentVector is only one implementation of it. Here's another:

user=> (instance? clojure.lang.IPersistentVector [1])
true
user=> (instance? clojure.lang.IPersistentVector (vector-of :long 1 2))
true
user=> (class (vector-of :long 1 2))
clojure.core.Vec
user=> 
Similarly, list and map are also abstractions and not concrete data-types. More on that in the docs: https://clojure.org/reference/data_structures#Vectors

🙌 1
Rushal Verma13:06:40

Thanks, I’ll read up more on this

respatialized15:06:28

Chapter 2.2 of Structure and Interpretation of Computer Programs, a classic textbook that uses Lisp to teach the fundamentals of programming, has a very good overview of the linked list data structure used across dialects of Lisp (including Clojure). https://sarabander.github.io/sicp/html/2_002e2.xhtml#g_t2_002e2_002e1

didibus21:06:10

Lists are singly-linked-list. You can implement "get" but you have to traverse all elements from the start so it's O(n). Get promises O(~1) lookup, which is why it's not implemented for lists. Rich Hickey likes operations to always have the same bigO no matter the data structure it's used on. Meaning he doesn't like implementing it on structures that would have a different bigO. In some cases, for convenience he broke the rule. He still somewhat regrets breaking the rule in those cases.

didibus21:06:46

Vectors are ArrayLists, so the elements can be accessed by index in O(1).

didibus21:06:48

Also, seqs and lists are not the same thing. Seqs are a very special data structures. The next element isn't stored in memory, it's a thunk that can compute the next element. When using nth you don't just have to iterate O(n) time, you also have to compute O(n) times the values of all elements in-between the start and the element you want.

didibus21:06:39

Seqs are great because they allow lazy behavior. And that lazy behavior simulates what you would do when breaking out of a loop early, or when using continue to skip over the inner loop on elements you don't care about. Without that, you can't implement certain algorithms in the same BigO as with imperative programming.

didibus22:06:43

Lists are kind of meh, but they have some advantages when all you need are stuff they can do. But it's pretty rare your use cases needs only what a List is good at.

didibus22:06:07

I believe Python Lists are ArrayList, so they're more like Vectors.

hrtmt brng20:06:15

Does (rest [1 2 3]) lose its vectorness? Is it internally still a vector? Would into [] be expensive?

Bob B20:06:44

rest (and many other seq operations) return a seq, so the answer to your first question is 'yes'. Expensive is sort of relative, but an alternative is subvec, which is a vector-specific operation, and returns a vector (and the docs mention that it's a constant-time op).

hrtmt brng21:06:46

Thank you. Subvec was what I was searching. So I guess (into [] (concat (rest [1 2 3]) [4])) is worse than (conj (subvec [1 2 3] 1) 4).

Bob B21:06:19

for collections that size, the time/space difference is probably not appreciable, but IMO, yeah, it's a bit worse because it's extra operations to think through when reading it

Olav Fosse21:06:55

(rest [1 2 3]) is still a vector under the hood. It’s just wrapped in a seq. A seq is a linked-list interface to an underlying data structure. https://clojure.org/reference/sequences

Olav Fosse21:06:36

So it depends on what you mean by vectorness.

Olav Fosse22:06:16

Afaik all the APIs are polite enough to only access through the seq interface.

mogverse11:06:21

@U06H2KWPRND then does calling (into []) turn it into vector again without conjing each element into a new vector?

Olav Fosse07:06:04

@U06RKJB7XN2 No, it uses the seq interface.

mogverse07:06:17

@U06H2KWPRND then I guess the "vectorness" goes away based on what the OP was asking

Olav Fosse10:06:53

@U06RKJB7XN2 yes, you’re right