【发布时间】:2014-06-02 17:56:27
【问题描述】:
让我们看看那个 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> 的东西。至少,我们有这个函数对象的命名空间和符号签名。
【问题讨论】:
-
“我的地图的键是指函数的符号”这是错误的,符号被解析并且地图中的键是函数对象。
-
@noisesmith 我刚刚更新了我的问题以反映这种区别,请查看并确保它涵盖了您在此处表达的内容。谢谢!
标签: clojure