same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)
;; See also https://clojure.org/namespaces for information on namespaces in Clojure and how to inspect and manipulate them
user=> (resolve 'x) nil user=> (def x 1) #'user/x user=> (resolve 'x) #'user/x user=> (resolve 'join) nil user=> (use '[clojure.string :only [join]]) nil user=> (resolve 'join) #'clojure.string/join user=> (join ", " ["a" "b"]) "a, b" user=> ((resolve 'join) ", " ["a" "b"]) "a, b"
;; Also takes a set/map of symbols to ignore while resolving. (defn replace-var [name value] (let [protected #{'+ '- '* '/}] (when (resolve protected name) (intern *ns* name value)))) (replace-var 'first last) (first [1 2 3 4]) ;; 4 ;; plus is protected. (replace-var '+ -) (+ 1 1) ;; 2
;; Also works fine on namespaced symbols ;; some-ns (def x 1) ;; other-ns @(resolve 'some-ns/x) ;; 1
;; (resolve env sym) can be used to detect what ;; the user is referring to at macro time. ;; The implied macro arg &env contains local bindings ;; of symbols when the macro is called. Resolve checks ;; if the symbol is contained within env. If (contains? env sym) ;; is true, resolve returns nil, meaning the symbol not referring ;; to anything globally, but rather to a local binding. ;; See (source ns-resolve). It's literally just a when check on the env arg. ;; Essentially, it boils down to four cases with (resolve env sym): ;; 1. Resolve returning a var. User is referring to a global var. ;; 2. Resolve returning a class. User is referring to global class. ;; 3. Resolve returning nil, and sym is contained in &env. ;; User is referring to something local. ;; 4. Resolve returning nil, and sym is not contained in &env. ;; It's an unresolvable symbol. ;; The &env map can be further examined to see what exactly the ;; local binding is, but bewarned that this is entering Clojure ;; compiler territory. (defmacro check-call "Checks if valid function call." [[sym & _ :as this]] (if (and (seq? this) (symbol? sym)) (if-some [v (resolve &env sym)] ; Resolve with &env (if (var? v) (println "Calling function on var:" v) (println "Cannot call class as function:" v)) (if (contains? &env sym) (println "Calling function on local binding:" sym) (println "Cannot call unresolvable symbol as function:" sym))) (println "Not function call."))) (check-call (map inc (range 10))) ;; => Calling function on var: #'clojure.core/map (check-call (java.util.Map)) ;; => Cannot call class as function: java.util.Map (let [map (fn [arg] (str "shadowed map " arg))] (check-call (map "foo"))) ; Calling the shadowed map, not clojure.core/map! ;; => Calling function on local binding: map (check-call (foobar)) ;; => Cannot call unresolvable symbol as function: foobar
Returns the var or Class to which a symbol will be resolved in the namespace (unless found in the ...
Returns a Symbol with the given namespace and name. Arity-1 works on strings, keywords, and vars.
Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, returns t...
Resolves namespace-qualified sym per 'resolve'. If initial resolve fails, attempts to require sym's ...
resolve