【问题标题】:Clojure: issues getting the symbol of a function in a looping contextClojure:在循环上下文中获取函数符号的问题
【发布时间】: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


【解决方案1】:
(def some-map {#'fn-key-1 "test-1"
               #'fn-key-2 "test 2"})

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

【讨论】:

  • 我没有想过在地图定义中直接使用#' 宏。但是,是否可以从该函数对象中获取引用该函数对象的符号?
  • 问题是每次我需要定义一些东西时,我都不想在这些地图的键前使用#'宏。
  • 函数对象不携带元数据,除非你把它放在那里。您使用的代码将元数据放在 var 上,而不是函数上。
  • 使用#'(或var 宏)是有意义的,因为var 可以获取它自己的数据,以及它所引用的东西。所指的事物故意不知道任何可能指向它的事物。
  • 拥有符号级别的元数据没有问题。但是你知道是否有可能获取引用对象(在本例中为函数对象)的符号列表?
猜你喜欢
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-22
  • 2014-08-22
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
相关资源
最近更新 更多