Clojure:我如何获取函数列表,转换它们,并返回原始名称的地图?

时间:2013-06-15 08:00:39

标签: clojure

好的,所以说我有一个功能列表: [f1 f2 f3]

我也有一个转换功能,我们称之为'trans'

我想要做的是将trans应用于原始列表中的每个函数,并返回一个映射,其键是与原始fxn名称对应的符号,其值是这些函数的转换版本:

{:f1 (trans f1) :f2 (trans f2) :f3 (trans f3)}

这可能是一个非常简单的问题,但我无法获取将函数名称转换为符号所需的元数据。

2 个答案:

答案 0 :(得分:2)

如果您的初始列表包含实际函数,而不是包含解析为此类Vars的函数或符号的Vars,那么通常没有规范的方法为它们分配名称,因为Clojure中的函数可能不一定具有名称。您可以获取函数对象的类的名称,并像clj-stacktrace那样处理它,以获得类似于人类可读的“名称”,但可能无法从该函数转换为函数。因此,在处理函数列表时,您可能需要考虑提供明确的名称列表。

如果您的列表包含符号,则可以执行

(zipmap fs (map (comp trans deref resolve) fs))

其中fs是输入列表,用于生成以fs成员为键的映射,以及由fs成员命名的变量函数存储在Vars中作为值。 (如果您希望将符号转换为关键字以匹配问题文本中显示的所需输出,则可以使用(map keyword fs)作为zipmap的第一个参数。)

同样,如果您有Vars列表,则可以从Vars中提取名称空间和符号名称(使用互操作表单访问clojure.lang.Var的相关字段,即sym和{{1使用ns来获取要传递给deref的函数。 (严格来说,Var可能没有附加名称空间或符号名称 - 请参阅trans;但是这些Vars并不经常使用,因此您可以合理地将其作为列表转换合同的一部分,而不是在其输入中找到任何内容。)

答案 1 :(得分:0)

您可以尝试使用如下所示的宏。您需要将函数列表直接传递给宏。

(defmacro fn-to-map [fns trans-fn]
  `~(into {} (map #(-> [(-> % name keyword) `(~trans-fn ~%)]) fns)))

示例:

(let [f1 inc
      f2 dec
      f3 print]
  (fn-to-map [f1 f2 f3] identity))