I suggested an improvement to @carocad's answer in a comment. Since I also needed to do this, and I needed to do it in both clj and cljs, here is what I came up with:
(ns my-ns.core
(:require [clojure.string :as s]
#?(:clj [clojure.main :refer [demunge]])))
(defn fn-name
[f]
#?(:clj
(as-> (str f) $
(demunge $)
(or (re-find #"(.+)--\d+@" $)
(re-find #"(.+)@" $))
(last $))
:cljs
(as-> (.-name f) $
(demunge $)
(s/split $ #"/")
((juxt butlast last) $)
(update $ 0 #(s/join "." %))
(s/join "/" $))))
Note that cljs.core has its own demunge built in and can't access clojure.main.
Edit
Note that when you do (with-meta a-fn {...}), it returns a clojure.lang.AFunction in clojure, which hides the underlying name and namespace information. There may be other situations like that, I'm not sure. With fn literal forms, you can do ^{...} (fn ...) instead of (with-meta (fn ...) {...}) and it won't return a clojure.lang.AFunction, but that workaround won't work with predefined functions. I haven't tested any of this in clojurescript to see if it works the same way.
Note also that anonymous functions in clojure will always end in fn, as in "my-ns.core/fn". Normally these functions would have a "--[0-9]+" at the end, but the regex above removes that. You could modify the function above and make an exception for anonymous functions. As long as the lambda has an internal name, that will be used, e.g.:
(fn-name (fn abc [x] x)) ;;=> "my-ns.core/abc"
Again, I haven't tested any of these notes in clojurescript yet.
(fn-name inc), whereas(let [f inc] (fn-name f))will fail. If you're typingincin literally, you can just type"inc"instead and save some characters!defns from the same namespace. Typing the function name also as a string isn't an option for me. I'm looking for how to get the name of any function passed as parameter.