Fork me on GitHub
#clojure
<
2022-08-13
>
Alejandro11:08:26

Why do data get packed in vectors instead of maps sometimes. This looks like alist in emacs. I'm pretty sure I've seen an explanation, but didn't read it and can't find it now. One possible purpose is to have an ordered map, but are there other considerations?

teodorlu13:08:00

Can you give an example? I don't understand what you mean.

Alex Miller (Clojure team)13:08:29

If you're thinking of like let bindings, it's to ensure ordering

Alejandro16:08:53

I mean malli , but I've seen this in other places as well.

seancorfield17:08:36

@U03RQQ5E8Q1 The choice of data structure is usually driven by the patterns of access (and sometimes construction). If you want O(1) lookup by (arbitrary) key, use a hash map (or a set); if you want O(1) lookup by index, use a vector. Vectors are optimized for adding elements at the end; lists are optimized for adding elements at the beginning. Both vectors and lists are great for ordered, sequential access; hash maps and sets are unordered.

teodorlu09:08:33

In malli / hiccup, vectors allow for concise, optional option maps.

;; with vectors:
[:a {:href "#section-2"} "Section 2"]

;; with a map:
{:tag :a
 :opts {:href "#sections"}
 :content "Section 2"}

;; but why not

{:a "Section 2"}

;; ?
;;
;; Well, where would you put the options?

teodorlu09:08:42

#cljfx has gone the "it's all maps" route:

(fx/on-fx-thread
 (fx/create-component
  {:fx/type :stage
   :showing true
   :title "Cljfx example"
   :width 300
   :height 100
   :scene {:fx/type :scene
           :root {:fx/type :v-box
                  :alignment :center
                  :children [{:fx/type :label
                              :text "Hello world"}]}}}))
(https://github.com/cljfx/cljfx#overview)

Alejandro15:08:01

@U3X7174KS, yeah, that's what I mean. Thanks for understanding my poorly formulated question. And thanks everyone. Some things are not immediately obvious.

👍 1
Takis_20:08:09

(let [f (fn [x y z] (println x y z))]
  ;;how to get metadata for f, for example the number of arguments it takes??
  )

gleenn00:08:50

(defn f [] 1)
(meta #'f)
=>
{:arglists ([]), :line 1, :column 1, :file "NO_SOURCE_PATH", :name f, :ns #object[clojure.lang.Namespace 0xf876b9e "user"]}

gleenn00:08:22

doens't work for fn's though:

user=> (def x (fn [] 2))
#'user/x
user=> (meta #'x)
{:line 1, :column 1, :file "NO_SOURCE_PATH", :name x, :ns #object[clojure.lang.Namespace 0xf876b9e "user"]}

gleenn00:08:00

the #' is the way to get the symbol from the var, or something like that, otherwise you get the value instead of the symbol which is the thing that has the meta data on it

Takis_20:08:21

is this possible?

p-himik20:08:25

No, because when you use defn, the metadata is attached to the resulting var. And in the case of let, there are no vars, so no metadata.

Takis_20:08:51

thank you p-himik : )

👍 1
dpsutton21:08:21

(let [f (fn [x y z] (println x y z))]
    (require 'clojure.reflect)
    (->> (clojure.reflect/reflect f)
         :members
         (filter #(instance? clojure.reflect.Method %))
         first
         :parameter-types
         count))

dpsutton21:08:06

(let [f (fn
            ([x] (println x))
            ([x y] (println x y))
            ([x y z] (println x y z)))]
    (require 'clojure.reflect)
    (->> (clojure.reflect/reflect f)
         :members
         (filter #(instance? clojure.reflect.Method %))
         (map (comp count :parameter-types))))

Takis_18:08:56

thank you dpsutton : )