Clojure:在循环上下文中获取函数符号的问题

时间:2014-06-02 17:56:27

标签: clojure

让我们来看看Clojure代码:

  (defn ^{:test-1 "meta-test-1"} fn-key-1 
    [x]
    (eval nil))

  (defn ^{:test-2 "meta-test-2"} fn-key-2 
    [x]
    (eval nil))

  (def some-map {fn-key-1 "test-1"
    fn-key-2 "test-2"})

如您所见,我的地图的键是指向功能的符号。我不知道那里有什么特别的东西。

正如您所看到的,在定义地图时,我的地图的键是引用功能的符号。但是,当读者阅读它们时,它们就会被解析为函数对象。

现在,我想要做的是迭代我的some-map地图以获取每个键的元数据。

我正在考虑这样做:

  (defn some-fn 
    [m]
    (doseq [[fn-key value] m]
      (println (meta fn-key))))

然而,这里印刷的是nil。这是预期的,因为元数据定义了符号,而不是函数。因此,该函数没有附加元数据,这就是返回/打印nil的原因。

所以这引出了一个问题:是否有可能获得引用我的功能的符号" fn-key"在那种情况下?

在该doseq循环中,似乎fn-key是一个函数,而不是该函数的符号。我需要的是一种获取该函数符号的方法,以便我可以使用(meta(get-symbol fn-key))。

问题解决

通过以下方式定义函数来解决这个问题:

(def fn-key-1
  (with-meta (fn [x] (eval nil)) {:foo "bar"}))

(def fn-key-2
  (with-meta (fn [x] (eval nil)) {:foo "bar"}))

修订决议案

我修改了上面的解决方案,使其更清洁。实际上,如果要在REPL中键入fn-key-1,则需要获得匿名函数引用,例如#< clojure.lang.AFunction$1@15ab1764>。问题在于,当您不知道正在评估什么时,它会使调试变得困难。为解决此问题,我更改了两个函数定义以使用此语法来解决此问题:

(def fn-key-1 ^{:foo "bar"} (fn [x] (eval nil)))

(def fn-key-2 ^{:foo "bar"} (fn [x] (eval nil)))

现在,如果我们输入fn-key-1,我们就会得到类似#<core$foo user.core$foo@66e37466>的内容。至少,我们有名称空间&amp;此函数对象的符号签名。

1 个答案:

答案 0 :(得分:1)

(def some-map {#'fn-key-1 "test-1"
               #'fn-key-2 "test 2"})
阅读器将

fn-key-1解析为函数对象(没有要查询的元数据)。 #'fn-key-1解析为var本身,并保存元数据。