I have a sequence of sequences, output from clojure-csv.
(def s1 [[:000-00-0000 "SMITH" "JOHN" 27][:000-00-0001 "FARMER" "FANNY" 28]])
I have a vector of column numbers [0 3] that I want to use to extract data from each sequence.
Rather than writing a function to zip together a variable number of map forms, I thought a macro might do the trick. But, I am having trouble.
This macro accepts a sequence and a column “mask”
(defmacro map-cols [seq & columns]
(for [col# columns
:let [mc# `(map #(nth % ~col# nil) ~seq)]]
mc#))
(map-cols s1 cols)
ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn bene-csv.core/eval2168
I was hoping to generate the multiple map forms that show up in
the following:
(zipmap (map #(nth % 0 nil) s1) (map #(nth % 1 nil) s1))
{:000-00-0001 "FARMER", :000-00-0000 "SMITH"}
I would appreciate some ideas of what I am doing wrong. I can, of course, just tailor the a function to the number of columns I need to extract.
Thank You.
Edit:
Modified macro
(defmacro map-cols [seq & columns]
(vec (for [col columns
:let [mc `(map #(nth % ~col nil) ~seq)]]
mc)))
(apply zipmap (map-cols s1 cols))
ArityException Wrong number of args (1) passed to: core$zipmap clojure.lang.AFn.throwArity
You are mixing up code that will execute at macro expansion with code that the macro will output. Until you enter a syntax-quote, you don’t need to use auto-gensym (col#, mc# in your example). As for the macro output, it must always produce exactly one form. It seems that you are expecting it to produce several forms (one for each col), but that’s not how this can work. Your macro output will currently look like
This is a form with two members. The member in the head position is expected to be a function, and the whole form is supposed to be evaluated as a function call.
The way to salvage this is to wrap your
forin the macro with avecand then use(apply zipmap (map-cols s1 cols)).That answers your immediate question, but the solution will still not make sense:
zipmapwants exactly two args, not a variable number of them as you said you want, and the output is a map, not a sequence that zips together your fields. Zipping is achieved using(map vector seq1 seq2 ...).