如何在Clojure中将函数的名称作为字符串?

Jin*_*arz 12 clojure

如何在Clojure中将函数的名称作为字符串?

到目前为止我所看到的并不像惯用语:

(defn fn-name
  [f]
  (first (re-find #"(?<=\$)([^@]+)(?=@)" (str f))))

(defn foo [])

(fn-name foo) ;; returns "foo"
Run Code Online (Sandbox Code Playgroud)

编辑:通过提供的提示,我把一个基本的宏放在一起,做我想要的.它看起来更好吗?

(defmacro fn-name
  [f]
  `(-> ~f var meta :name str))
Run Code Online (Sandbox Code Playgroud)

noi*_*ith 8

对于使用以下defn形式定义的函数:

user> (-> #'map meta :name)
map
user> (defn nothing [& _])
#'user/nothing
user> (-> #'nothing meta :name)
nothing
Run Code Online (Sandbox Code Playgroud)

这需要访问var,而不仅仅是var保存的函数值.


car*_*cad 5

编辑:我发现了一种更好的方式 Clojure 包含一个名为 demunge 的函数。因此,与其重新发明轮子,不如直接使用它;)

(clojure.repl/demunge (str map?));; "clojure.core/map?@2b68895c"
Run Code Online (Sandbox Code Playgroud)

或者如果你想要一个美化版

(defn- pretty-demunge
  [fn-object]
  (let [dem-fn (demunge (str fn-object))
        pretty (second (re-find #"(.*?\/.*?)[\-\-|@].*" dem-fn))]
    (if pretty pretty dem-fn)))

(pretty-demunge map?);; "clojure.core/map?"
Run Code Online (Sandbox Code Playgroud)

我认为有一种更干净的方法可以做到这一点。我遇到了同样的问题,想知道作为函数参数的函数名称。我无法使用宏,因为我需要映射它,所以这里是我得到的:(假设是字符串?函数是作为参数传递的)

(clojure.string/replace (second (re-find #"^.+\$(.+)\@.+$" (str string?)))
                        #"\_QMARK\_" "?")
; string?
Run Code Online (Sandbox Code Playgroud)

当然,这不是一个完整的解决方案,但我相信您可以从这里开始。基本上 Clojure 将函数名称修改为可以使用的名称。所以基本的显然是:你需要解开那个!这很容易,因为 str 可用于任何函数 :D ,返回函数的重整名称。

顺便说一句,这也有效

(def foo string?)
(clojure.string/replace (second (re-find #"^.+\$(.+)\@.+$" (str foo)))
                        #"\_QMARK\_" "?")
; string?
Run Code Online (Sandbox Code Playgroud)

玩得开心