[英]Writing Clojure Macro To Generate map Forms
我有一個序列序列,從clojure-csv輸出。
(def s1 [[:000-00-0000 "SMITH" "JOHN" 27][:000-00-0001 "FARMER" "FANNY" 28]])
我有一個列號[0 3]的向量,我想使用該向量從每個序列中提取數據。
我認為編寫宏可能會解決問題,而不是編寫將不同數量的地圖表單壓縮在一起的函數。 但是,我遇到了麻煩。
該宏接受一個序列和一列“掩碼”
(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
我希望生成以下顯示的多個地圖形式:
(zipmap (map #(nth % 0 nil) s1) (map #(nth % 1 nil) s1))
{:000-00-0001 "FARMER", :000-00-0000 "SMITH"}
對於我在做什么錯,我將不勝感激。 當然,我可以根據需要提取的列數來定制a函數。
謝謝。
編輯:
修改后的宏
(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
您正在混合將在宏擴展時執行的代碼與該宏將輸出的代碼。 在輸入語法引號之前,無需使用auto-gensym(在示例中為col#,mc#)。 至於宏輸出,它必須始終產生恰好一種形式。 似乎您期望它會生成多種形式(每個列對應一個),但這不是可行的。 您的宏輸出當前看起來像
((map #(nth % 0 nil) s1) (map #(nth % 1 nil) s1))
這是一個有兩個成員的表格。 處於頭部位置的成員應該是一個函數,並且應該將整個表單評估為一個函數調用。
解決這個問題的方法是使用vec
將for
包裹在宏中,然后使用(apply zipmap (map-cols s1 cols))
。
這回答了您的緊迫問題,但解決方案仍然沒有意義: zipmap
恰好需要兩個args,而不是您想要的可變數量的參數,並且輸出是映射,而不是將字段壓縮在一起的序列。 使用(map vector seq1 seq2 ...)
實現壓縮。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.