Imagine that:
(def my-var 'my-symbol) ;; Please note that it must be 'my-symbol not `my-symbol
my-var ;; => my-symbol
But I want
;; => fully-qualified/my-symbol
Other than converting values to strings, is it possible to fully qualify my-var's value? Thanks.
Use a back quote instead of a straight quote:
(def my-var `my-symbol) ; and not 'my-symbol
Since symbols are created from strings (see here) and they are immutable, in order to build a fully qualified symbol from a symbol a conversion to String is inevitable.
(symbol (name (ns-name *ns*)) (name 'my-symbol))
Keywords are also able to be fully qualified. The value ::my-keyword will be expanded by the reader to be fully qualified, taking the namespace where the value is being read.
::my-keyword
;;= :user/my-keyword
(ns other-ns)
::my-keyword
;;= :other-ns/my-keyword
They are more broadly used in Clojure when you need fully qualified values.
Related
When I use some long function names, I used the use form, like this:
(use '[clojure.string :as str])
But I don't know why add a single quote ' to the vector, so I tried to figure out its type:
(type '[clojure.string :as str])
;=> clojure.lang.PersistentVector
Simplified example:
(type ["hello"])
;=> clojure.lang.PersistentVector
(type '["hello"])
;=> clojure.lang.PersistentVector
It seems the single quote doesn't change anything, can anybody explain the usage of it in the use form?
The intent is to quote the symbols. This way they'll be treated as symbols, and use can take those symbols as naming a namespace to load and pull into the current. You want to avoid the default treatment of a symbol, which is resolving it as the name of a Var and using the value of that Var. You can also do this as
(use ['clojure.string :as 'str])
but that involves some unnecessary typing; quoting the whole vector makes you less likely to forget anything. Particularly if you're doing anything with :only, :refer or similar keyword arguments.
Aside: ns doesn't need this because as a macro it can control evaluation of its arguments - functions like require and use have all their arguments read and evaluated before they themselves run. This is part of the reason why ns is normally preferred over those functions.
use is a function, hence the evaluator evaluates its arguments before they are passed (applicative order evaluation).
You don't want [clojure.string :as str] to be evaluated as the evaluator would try to resolve the symbols in it with no success before applying use.
Hence quote (reader shorthand ') is there to prevent their evaluation.
If I have a symbol who's namespace is an alias, like q/w, how can I find its actual namespace, say actual.namespace/w ?
I know that resolve will give me the fully qualified var, but I don't know how to get the namespace of a var.
The best I can do is:
(defn fqns [s] (str (get (ns-aliases *ns*) (symbol (namespace s)))))
surely there's a simpler way ?
You can get the namespace object of a symbol as shown below (if you want name of ns as string then just call str at the end):
(defn fqns [s] (->> (resolve s) meta :ns))
The symbol itself has no direct connection to any namespace object; its namespace part is just an interned string. It is only when it's being resolved that this string is treated as the name of an actual namespace in which to look up a Var. (In particular, you can create a symbol foo/bar without creating a namespace foo or registering foo as an alias for a namespace.) Thus, you need to either go through resolve or do part of its work yourself.
In the first case, you can say (in recent versions of Clojure; or you can skip the hyphens signifying property access -- instead of -ns, use ns -- to be backwards compatible)
(.. (resolve s) -ns -name)
This resolves a Var object, then extracts a reference to its namespace from its ns field and finally extracts the symbolic name of the namespace from its name field. (Note that the namespace and name functions wouldn't work, since Vars and namespaces do not implement clojure.lang.Named.)
The function from the question text is fine too, although it'll be better to extract the symbol name from the namespace -- (.-name (get ...)) -- rather than rely on the toString representation of namespaces through the use of str.
You may also want to add clojure.lang.Var and clojure.lang.Namespace type hints to avoid reflection in your calls. (If you want them to be faster, or if you need *warn-on-reflection* to tweak something else for performance and wish to avoid useless warnings here.)
If you wish to handle the possibility that the namespace does not exist (and return nil in that case, in keeping with usual Clojure idiom):
(defn fqns
([s]
(fqns (.-name *ns*) s))
([ns s]
(some-> ns
find-ns
.-name
ns-aliases
(get (symbol (namespace s)))
.-name)))
Or use some if-lets in Clojure 1.4 and earlier.
I recently learned (thanks to technomancy) that, at the REPL ---
This fails:
user=> (:require [clojure.set :as set])
java.lang.ClassNotFoundException: clojure.set (NO_SOURCE_FILE:24)
Whereas this succeeds :
user=> (require '[clojure.set :as cs])
nil
at loading the clojure.set class.
Context: The former line was copied from a namespaced source file.
My primary question is : What is the change we have made, by swapping the : and ' characters, which now allows for success of the latter command ?
My 2nd question is , in general - what are the guidelines for doing things at the REPL --- as compared with doing things in normal clojure source files ? Assume here that we can load our repl from the root of a LEININGEN project, so at least the jars will be available on disk in the dependencies sub directory.
I'll go from high-level down to your particular problem:
How Clojure (or LISPs) Generally Work
REPLs, or Read-Eval-Print Loops are the core of how LISPs are designed:
The reader converts a stream of characters into data structures (called Reader Forms).
The evaluator takes collection of reader forms and evaluates them.
The printer emits the results of the evaluator.
So when you enter text into a REPL, it goes through each of these steps to process your input and return the output to your terminal.
Reader Forms
First some, clojure reader forms. This will be extremely brief, I encourage you to read or watch (part 1, part 2) about it.
A symbol in clojure is form that can represent a particular value (like a variable). Symbols themselves can be pass around as data. They are similar to pointers in c, just without the memory management stuff.
A symbol with a colon in front of it is a keyword. Keywords are like symbols with the exception that a keyword's value are always themselves - similar to strings or numbers. They're identical to Ruby's symbols (which are also prefixed with colons).
A quote in front of a form tells the evaluator to leave the data structure as-is:
user=> (list 1 2)
(1 2)
user=> '(1 2)
(1 2)
user=> (= (list 1 2) '(1 2))
true
Although quoting can apply to more than just lists, it's primarily used for lists because clojure's evaluator will normally execute lists as a function-like invocation. Using the ' is shorthand to the quote macro:
user=> (quote (1 2)) ; same as '(1 2)
(1 2)
Quoting basically specifies data structure to return and not actual code to execute. So you can quote symbols which refers to the symbol.
user=> 'foo ; not defined earlier
foo
And quoting is recursive. So all the data inside are quoted too:
user=> '(foo bar)
(foo bar)
To get the behavior of (foo bar) without quoting, you can eval it:
user=> (eval '(foo bar)) ; Remember, foo and bar weren't defined yet.
CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:1)
user=> (def foo identity)
#'user/foo
user=> (def bar 1)
#'user/bar
user=> (eval '(foo bar))
1
There's a lot more to quoting, but that's out of this scope.
Requiring
As for require statements, I'm assuming you found the former in the form of:
(ns my.namespace
(:require [clojure.set :as set]))
ns is a macro that will transform the :require expression into the latter form you described:
(require '[clojure.set :as set])
Along with some namespacing work. The basics are described when asking for the docs of ns in the REPL.
user=> (doc ns)
-------------------------
clojure.core/ns
([name docstring? attr-map? references*])
Macro
Sets *ns* to the namespace named by name (unevaluated), creating it
if needed. references can be zero or more of: (:refer-clojure ...)
(:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
with the syntax of refer-clojure/require/use/import/load/gen-class
respectively, except the arguments are unevaluated and need not be
quoted. (:gen-class ...), when supplied, defaults to :name
corresponding to the ns name, :main true, :impl-ns same as ns, and
:init-impl-ns true. All options of gen-class are
supported. The :gen-class directive is ignored when not
compiling. If :gen-class is not supplied, when compiled only an
nsname__init.class will be generated. If :refer-clojure is not used, a
default (refer 'clojure) is used. Use of ns is preferred to
individual calls to in-ns/require/use/import:
REPL usage
In general, don't use ns in the REPL, and just use the require and use functions. But in files, use the ns macro to do those stuff.
The difference is that require is a function used for importing code, whereas :require is a keyword.
Remember what happens when you use a keyword as a function:
=> (type :require)
clojure.lang.Keyword
=> (:require {:abc 1 :require 14})
14
it looks itself up in the map. So when you pass [clojure.set :as set] to a keyword, it's trying to evaluate that to a vector, and fails because it doesn't know what clojure.set is. The Clojure docs say:
Keywords implement IFn for invoke() of one argument (a map) with an
optional second argument (a default value). For example (:mykey
my-hash-map :none) means the same as (get my-hash-map :mykey :none).
You may have been confused by the ns macro:
(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql sql.tests)) ;; here's :require!
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement)))
ns macro:
When you type:
(ns some-great-ns
:require my-form)
you use the :require reference in which you state what would you like to use from the given namespace. It is equivalent to writing:
(in-ns 'some-great-ns)
(require 'my-form)
Notice that in the ns form (unlike the in-ns function call), you don’t have to quote your symbol with '. You never have to quote symbols within ns.
require function
As stated, can run: (require 'some-great-ns) in some given namespace so you could use it. To use it, you'll have to use full qualified name, unless you also use: refer function: (refer 'some-great-ns) right after you required the namespace.
You can do those both functions in one: (use 'some-great-ns). Now you don't need to write: (some-great-ns/my-form). Simply: my-form.
And of course you can also use the :as, :exclude, :only and :rename keywords in both the macro reference and in the function.
Differences between the macro and the function:
As stated above, usage of symbols in function, no need in the macro
You can require multiple libraries in a (:require) reference as follows:
(ns my-great-namespace.core
(:require [some-other-ns.a.b :as ab]
[some-other-other-ns.c.d :as cd]))
Where in function writing you should write 2 lines:
(in-ns my-great-namespace.core)
(require 'some-other-ns.a.b :as 'ab)
(require 'some-other-other=ns.c.d :as 'cd)
The require reference also allows you to refer names, for example:
(ns my-great-namespace.core
(:require [some-other-ns.a.b :refer [some-func]]))
Where in function you should do:
(in-ns my-great-namespace.core)
(require 'some-other-ns.a.b)
(refer 'some-other-ns.a.b :only ['some-func])
How can I test wether a variable has been declared or assigned (i.e. check if "a" is defined, when I expect a program to call some code like this (def a (create-a)) ?
And related --- how does the answer to this question relate to the problem of resolving a symbol (i.e. a function) which has been declared ? Clojure: determine if a function exists
It seems like a defined variable should be checkable in the same sense that a defined function is, but I'm finding that the solution for determining if a function exists is not sufficient for determining wether a variable exists.
Some context : I'm writing unit tests for a multideveloper project, and want to make sure that the test data, and the methods in different classes have been defined. Since there is no good IDE support for clojure, it seems to me that, given its loose structure, it is good to test method names and variable names existence before testing their outputs / content.
You can use resolve to see if the variable was bound/defined:
(resolve 'meaning)
nil
(def meaning 42)
#'user/meaning
(resolve 'meaning)
#'user/meaning
or you can boolean check it, if you need true/false:
(boolean (resolve 'meaning))
true
One way to do this is to use ns-resolve, for example:
user=> (def a "hello a")
user=> (ns-resolve *ns* 'a)
#'user/a
user=> (ns-resolve *ns* 'b)
;nil ; This assumes b hasn't been defined before...
Note that if you namespace-qualify the symbol to be checked then what you pass as first argument (*ns* in the example above) doesn't matter:
user=> (ns-resolve 'user 'a)
#'user/a
user=> (ns-resolve 'other 'a)
nil
user=> (ns-resolve 'other 'user/a)
#'user/a
The resolve function mentioned by #tolitius is actually a shorthand for ns-resolve where the namespace argument always evaluates to ns, depending on the use case it might be more handy.
As others have said, resolve will return the var for a symbol if there is one defined, or nil. Further, you can check if the var has a value bound to it by using bound?.
user=> (resolve 'foo)
nil
user=> (def foo)
#'user/foo
user=> (resolve 'foo)
#'user/foo
user=> (bound? #'foo)
false
user=> (def foo 5)
#'user/foo
user=> (bound? #'foo)
true
Since there is no good IDE support for clojure it seems to me that,
given its loose structure, it is good to test method names and
variable names existence before testing their outputs / content.
This is nuts. You really want a test to say "Oops! You forgot to define foobar!" instead of just trying to run foobar and seeing Clojure's "Unable to resolve symbol" message?
What do you gain from this? You lose the stacktrace, which could be useful if, for example, the test is passed the wrong function name by some other code. Much better to know what line mis-spelled foobar than to search through your whole test namespace.
I want to check if a symbol is resolvable in the current namespace. What's the canonical way to do this?
After sifting through the API docs once more, I've stumbled on what might be the appropriate function:
; Returns the var or Class to which the symbol
; will be resolved in the current namespace, else nil.
(resolve 'foo)
; see also:
(ns-resolve *a-namespace* 'foo)
Take a look at this page. For example
(ns-map *ns*)
will give you a map of the bindings in the current namespace. You can examine this map to decide if your symbol is a key in the map,
(defn resolvable? [sym]
(contains? (ns-map *ns*) sym))
I do not know if this is the canonical way.