簡體   English   中英

編寫Clojure宏以生成地圖表單

[英]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))

這是一個有兩個成員的表格。 處於頭部位置的成員應該是一個函數,並且應該將整個表單評估為一個函數調用。

解決這個問題的方法是使用vecfor包裹在宏中,然后使用(apply zipmap (map-cols s1 cols))

這回答了您的緊迫問題,但解決方案仍然沒有意義: zipmap恰好需要兩個args,而不是您想要的可變數量的參數,並且輸出是映射,而不是將字段壓縮在一起的序列。 使用(map vector seq1 seq2 ...)實現壓縮。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM