Function 如何从clojure中的符号中获取函数名?
假设我将x定义为符号函数fooFunction 如何从clojure中的符号中获取函数名?,function,clojure,symbols,name-lookup,Function,Clojure,Symbols,Name Lookup,假设我将x定义为符号函数foo (defn foo [x] x) (def x foo) 如果只给定x,是否可以发现名称“foo” 在foo中是否有方法查找函数x的名称?在本例中为“foo” (foo x) 是否存在或可能创建以下功能: (get-fn-name x) foo 不清楚您为什么要这样做-当您这样做(def x foo)时,实际上是将名称x赋予命名空间中的新变量。它恰好与foo具有相同的值(即,它包含相同的函数),但在其他方面完全独立于foo。使用Java类比,这就像对同一个
(defn foo [x] x)
(def x foo)
如果只给定x,是否可以发现名称“foo”
在foo中是否有方法查找函数x的名称?在本例中为“foo”
(foo x)
是否存在或可能创建以下功能:
(get-fn-name x)
foo
不清楚您为什么要这样做-当您这样做
(def x foo)
时,实际上是将名称x
赋予命名空间中的新变量。它恰好与foo
具有相同的值(即,它包含相同的函数),但在其他方面完全独立于foo。使用Java类比,这就像对同一个对象有两个引用一样
为什么要继续获取名称foo
如果确实希望执行类似的操作,可以在包含原始符号的函数上使用一些自定义元数据:
(def foo
(with-meta
(fn [x] x)
{:original-function `foo}))
(def bar foo)
(defn original-function [v]
"Returns the :original-function symbol from the metadata map"
(:original-function (meta v)))
(original-function bar)
=> user/foo
最近在这个网站上也提出了类似的问题;看 当您执行
(def x foo)
时,您将x定义为“位于foo
的值”,而不是“foo
本身”。一旦foo
解析为其值,该值就不再与foo
有任何关系
因此,也许您现在看到了问题的一个可能答案:当您开始定义x
时,不要解析foo
。而不是做
(def x foo)
…做
(def x 'foo)
现在,如果您尝试获取x
的值,您将获得foo
(字面意思),而不是foo
解析为的值
user> x
=> foo
但是,这可能有问题,因为有时您可能还希望能够使用x
获得foo
解析为的值。但是,您可以通过执行以下操作来做到这一点:
user> @(resolve x)
=> #<user$foo user$foo@157b46f>
现在,看看这个:
user> (str foo)
=> "user$foo@1e2afb2"
user> (str x)
=> "user$foo@1e2afb2"
酷。这仅仅是因为foo
解析为一个函数,该函数恰巧有一个类似var的名称,该名称与x
相同,因为它引用了相同的函数。请注意,“foo”包含在(strx)
(以及(foo x)
)生成的字符串中。这是因为函数的var名称显然是通过向后引用最初用于定义它的符号创建的。我们将利用这个事实,从任何函数中找到这个符号
所以,我写了一篇文章来查找函数var名称字符串中的“foo”。它不是查找“foo”,而是查找任何子字符串——用正则表达式术语,
“*”
——前面有一个\$
字符——用正则表达式术语,”(?谢谢,这对我有用。我需要函数能够报告它自己的名称(也许它可以更直接地这样做?)以及它作为参数接收的其他函数的名称。很高兴它能为您工作。尽管我会仔细考虑您正在做什么-使函数“能够报告自己的名称”"听起来你试图强迫函数做一些它们不是为之设计的事情。如果你试图让函数以类似对象的方式运行,也许你应该改用defrecord?这是一个令人惊讶的答案,方法一正是我所需要的。如果你已经写了一本关于Clojure的书,或者正在计划一本,请告诉我。我会的买吧。
user> (str foo)
=> "user$foo@1e2afb2"
user> (str x)
=> "user$foo@1e2afb2"
user> (re-find #"(?<=\$).*(?=@)"
(str x))
=> "foo"
user> (symbol (re-find #"(?<=\$).*(?=@)"
(str x)))
=> foo
(defn get-fn-init-sym [f]
(symbol (re-find #"(?<=\$).*(?=@)" (str f))))
(defn get-fn-init-sym [f]
(->> (str f)
(re-find #"(?<=\$).*(?=@)")
symbol))
user> (get-fn-init-sym x)
=> foo
user> (->> (dissoc (ns-map *ns*) 'x)
(filter #(identical? (let [v (val %)]
(if (var? v) @v v))
x))
first
key)
=> foo
(defn find-equiv-sym [sym]
(->> (dissoc (ns-map *ns*) sym)
(filter #(identical? (let [v (val %)]
(if (var? v) @v v))
@(resolve sym)))
first
key))
user> (find-equiv-sym 'x)
=> foo