好的,假设我有一个函数列表:[f1 f2 f3]
我还有一个转换函数,我们称它为“trans”
我想要做的是将 trans 应用于原始列表中的每个函数,并返回一个映射,其键是与原始 fxn 名称相对应的符号,其值是这些函数的转换版本:
{:f1 (trans f1) :f2 (trans f2) :f3 (trans f3)}
这可能是一个非常简单的问题,但我无法获取将函数名称转换为符号所需的元数据。
好的,假设我有一个函数列表:[f1 f2 f3]
我还有一个转换函数,我们称它为“trans”
我想要做的是将 trans 应用于原始列表中的每个函数,并返回一个映射,其键是与原始 fxn 名称相对应的符号,其值是这些函数的转换版本:
{:f1 (trans f1) :f2 (trans f2) :f3 (trans f3)}
这可能是一个非常简单的问题,但我无法获取将函数名称转换为符号所需的元数据。
如果您的初始列表包含实际函数,而不是 Vars 包含解析为此类 Vars 的函数或符号,那么通常没有为它们分配名称的规范方法,因为 Clojure 中的函数可能不一定有名称。您可以获取函数对象的类的名称并像clj-stacktrace那样处理它以获得类似于人类可读的“名称”的东西,但可能无法从该名称转到函数。因此,在处理函数列表时,您可能需要考虑提供一个明确的名称列表。
如果您的列表包含符号,您可以这样做
(zipmap fs (map (comp trans deref resolve) fs))
其中fs
是生成映射的输入列表,其中的成员fs
作为键,转换后的函数存储在由成员命名的变量中fs
作为值。(如果您希望将符号转换为关键字以匹配问题文本中显示的所需输出,则可以将(map keyword fs)
其用作 的第一个参数zipmap
。)
类似地,如果您有一个 Var 列表,您可以从 Var 中提取名称空间和符号名称(使用互操作表单来访问 的相关字段clojure.lang.Var
,即sym
和ns
),同时使用deref
来获取要馈送到的函数trans
。(严格来说,一个 Var 可能没有附加名称空间或符号名称 - 请参阅with-local-vars
;尽管此类 Var 的使用并不频繁,因此您可以合理地将其作为列表转换合同的一部分,它希望在其输入。)
您可以尝试如下所示的宏。您需要将函数列表直接传递给宏。
(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))