编写Clojure宏以生成映射表单

编写Clojure宏以生成映射表单,clojure,Clojure,我有一个序列,从clojure csv输出 (def s1 [[:000-00-0000 "SMITH" "JOHN" 27][:000-00-0001 "FARMER" "FANNY" 28]]) 我有一个列编号[03]的向量,我想用它从每个序列中提取数据 我认为宏可以实现这一点,而不是编写一个函数来压缩不同数量的映射表单。但是,我有麻烦了 此宏接受序列和列“掩码” 我希望生成在中显示的多个地图表单 以下是: (zipmap (map #(nth % 0 nil) s1) (map #(nt

我有一个序列,从clojure csv输出

(def s1 [[:000-00-0000 "SMITH" "JOHN" 27][:000-00-0001 "FARMER" "FANNY" 28]])
我有一个列编号[03]的向量,我想用它从每个序列中提取数据

我认为宏可以实现这一点,而不是编写一个函数来压缩不同数量的映射表单。但是,我有麻烦了

此宏接受序列和列“掩码”

我希望生成在中显示的多个地图表单 以下是:

(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))
这是一个有两个成员的表格。处于head位置的成员应该是一个函数,整个表单应该作为函数调用进行计算

补救方法是在宏中用
vec
包装
for
,然后使用
(apply zipmap(map cols s1 cols))


这回答了您当前的问题,但解决方案仍然没有意义:
zipmap
只需要两个参数,而不是您所说的数量可变的参数,并且输出是一个映射,而不是将字段压缩在一起的序列。压缩是通过使用
(映射向量seq1 seq2…

实现的。您将在宏展开时执行的代码与宏将输出的代码混合在一起。在输入语法引号之前,不需要使用auto-gensym(示例中为col#,mc#)。至于宏输出,它必须始终只生成一个表单。看起来您希望它生成多个表单(每个列一个表单),但这不是它的工作方式。您的宏输出当前看起来像

((map #(nth % 0 nil) s1) (map #(nth % 1 nil) s1))
这是一个有两个成员的表格。处于head位置的成员应该是一个函数,整个表单应该作为函数调用进行计算

补救方法是在宏中用
vec
包装
for
,然后使用
(apply zipmap(map cols s1 cols))


这回答了您当前的问题,但解决方案仍然没有意义:
zipmap
只需要两个参数,而不是您所说的数量可变的参数,并且输出是一个映射,而不是将字段压缩在一起的序列。压缩是使用
(映射向量seq1 seq2…

实现的,我不太确定您希望我做什么编辑,所以我编辑了原始问题和输出。谢谢。风格评论:你的:让[mc…]是多余的。直接生成结果:(对于[col列]`(map#(n%~col nil)~seq))。至于你的新问题,正如我所说的,zipmap只需要两个arg。您现在只给了它一个,因为您只调用了一列宏。很抱歉,我无法编译更改。(defmacro map cols[seq&columns](vec(for[col columns`(map#(nth%~col nil)~seq)))您将右括号放错了(应该放在列之后)。和我的比较。我不太确定你们要我做什么编辑,所以我编辑了原始问题和输出。谢谢。风格评论:你的:让[mc…]是多余的。直接生成结果:(对于[col列]`(map#(n%~col nil)~seq))。至于你的新问题,正如我所说的,zipmap只需要两个arg。您现在只给了它一个,因为您只调用了一列宏。很抱歉,我无法编译更改。(defmacro map cols[seq&columns](vec(for[col columns`(map#(nth%~col nil)~seq)))您将右括号放错了(应该放在列之后)。和我的相比。