I really don't understand what is this macro.
(def n 12)
=> #'lambda.core-test/n
#'n
=> #'lambda.core-test/n
(= #'n n)
=> false
(= #'n #'n)
=> true
(= 12 #'n)
=> false
I read somewhere that #'x is the same as (var x) so
(var n)
=> #'lambda.core-test/n
(var-get (var n))
=> 12
People seems to use it when reevaluation the definition of symbol doesn't work in REPL.
What exactly does this macro and how does it relates to reevaluation ?
#'x is just shorthand for (var x)
https://clojuredocs.org/clojure.core/var
http://clojure.org/special_forms
The reason you would use either of these, is when you want to refer to the variable itself rather than the value stored within the variable. For example, you may want to write a doc generator that pulls the docstrings, arglists and other meta info from a set of vars. To do this you could use:
(def some-var "With a docstring" 1)
(meta (var some-var)) ;; or
(meta #'some-var)
I most frequently use this reader macro in conjunction with Stuart Sierra's component library. https://github.com/stuartsierra/component
For example, after defining a new system (using the component lib), I often need to do some stateful mutation to the defined system to start or stop it. Instead of referring to the immutable value as defined in var x, acting upon it, and then returning a new immutable value y, I want to update the value of var x in place, changing the actual var x itself. Here's a code example.
(require 'com.stuartsierra.component)
(def x (new-system))
(alter-var-root #'x com.stuartsierra.component/start)
https://clojuredocs.org/clojure.core/alter-var-root
FWIW most clojure devs won't touch this reader macro in their day to day work, but definitely worth having a grasp on. Hopefully that helps!
Related
With Clojure 1.9-beta2, the reader and writer now support a compact syntax for maps. The syntax avoids repeating the namespace in the case where all the keys are qualified keywords with the same namespace:
> (pr-str {:a/foo 1 :a/bar 2})
"#:a{:foo 1, :bar 2}"
That causes problem when sending such a serialized map to a Clojure 1.8 process: the old reader running there will fail to read it and throw a java.lang.RuntimeException: Reader tag must be a symbol.
Luckily, the printer only does this when the dynamic variable *print-namespace-maps* is truthy, and it's falsey by default, so my app continues to work in production. However, the REPL sets it to true, so when I work in the REPL and do something that ends up sending a request to a Clojure 1.8 service, it fails. How can I disable the new syntax in the REPL also?
I thought that maybe I could just (set! *print-namespace-maps* false) in my repl or add {:user {:repl-options {:init (set! *print-namespace-maps* false)}}} to my ~/.lein/profiles.clj, but that doesn't seem to work. I think the reason may be that the REPL uses binding to create thread-local bindings for a bunch of variables including this one, and set! does not work for local variable bindings.
You can redefine print-method for maps, which should work regardless of environment.
(defmethod print-method clojure.lang.IPersistentMap [m, ^java.io.Writer w]
(#'clojure.core/print-meta m w)
(#'clojure.core/print-map m #'clojure.core/pr-on w))
Using (set! *print-namespace-maps* false) works for me. (But this is some 5 years later.)
This also works, and can sometimes be more desirable:
(binding [*print-namespace-maps* false]
(pr-str {:a/foo 1 :a/bar 2}))
=> "{:a/foo 1, :a/bar 2}"
I've got a dynamic var in a namespace defined in a source file, like this:
(ns mystuff.log ...)
(def ^:dynamic *logging* #{})
I'd like to be able to set! this var from the REPL, so that code in that same source file can look at it. In this example, the mystuff.log/log macro looks at *logging* to decide whether to print a given expression. At the REPL, it would be convenient to (set! *logging* #{:whatever}), changing its value multiple times during the session.
How can I get Leiningen's REPL to allow this? By default, set!ing such a var produces an IllegalStateException because set! can't change the root binding of a var. The var must be thread-local to be changeable by set!.
Is there a way to tell Leiningen to wrap its REPL something like this, to create a thread-local binding for a var?
(binding [mystuff.log/*logging* mystuff.log/*logging*]
(the-leiningen-repl ...))
The :init option of :repl-options, briefly explained here, seems like it offers something close. Apparently, though, the REPL calls :init, which would make it too late to establish a thread-local binding for the expressions typed into the REPL.
You probably want alter-var-root, not set!. With no special set-up or modifications to the REPL, here's what you can do:
user> (def logging #{})
#'user/logging
user> (alter-var-root #'logging conj :my-new-logger)
#{:my-new-logger}
user> (alter-var-root #'logging conj :another-new-logger)
#{:my-new-logger :another-new-logger}
user> logging
#{:my-new-logger :another-new-logger}
#{:my-new-logger :another-new-logger}
set! modifies only a var's current thread binding. alter-var-root modifies the var's root binding: the value that's shared across all threads where it's not overridden by a per-thread binding.*
*By the way, that's why alter-var-root doesn't have an exclamation point. It follows the same convention as other forms that modify root bindings, like def.
Based on command-line input, I need to set some run-time constants which a number of downstream functions are going to use. The code in those functions may execute in other threads so I am not considering the "declare var and use binding macro" combination. What are the pros/cons of using a var (with alter-var-root) for this versus using an atom? That is,
(declare *dry-run*) ; one of my constants
(defn -main [& args]
; fetch command line option
;(cli args ...)
(alter-var-root #'*dry-run* (constantly ...))
(do-stuff-in-thread-pool))
versus
(def *dry-run* (atom true))
(defn -main [& args]
; fetch command line option
;(cli args ...)
(reset! *dry-run* ...)
(do-stuff-in-thread-pool))
If there is another option besides these two which I should consider, would love to know.
Also, ideally I would've preferred not to provide an initial val to the atom because I want to set defaults elsewhere (with the cli invocation), but I can live with it, especially if using the atom offers advantages compared to the alternative(s).
Write-once values are exactly the use case promises are designed for:
(def dry-run (promise))
(defn -main []
(deliver dry-run true))
(defn whatever [f]
(if #dry-run
...))
AFAIK alter-var-root only guarantees synchronized variable value changing and doesn't guarantee safe reading during this change. On other hand the atom really provides atomically change the state of identity.
If you don't want provide an initial value you can just set it to nil:
(def *dry-run* (atom nil))
What is wrong with just using a var and alter-var-root? You set up the new value in your startup function, before you really kick-off the workers. So there is no race in reading. And you can save the # everywhere you need the value.
In the compojure library in the core namespace, I see the following form:
(defn- compile-route
"Compile a route in the form (method path & body) into a function."
[method route bindings body]
`(#'if-method ~method
(#'if-route ~(prepare-route route)
(fn [request#]
(let-request [~bindings request#]
(render (do ~#body) request#))))))
and
(defmacro GET "Generate a GET route."
[path args & body]
(compile-route :get path args body))
Further up in the file, the if-method and if-route functions are defined with defn-s.
I don't understand the meaning of the #' in this compile-route function though. The docs for (var ...) says:
The symbol must resolve to a var, and the Var object itself (not its value) is returned. The reader macro #'x expands to (var x).
But to me, in the context of what is happening (ie being called from a defmacro), it just sounds like it means the value of the symbol will be returned, which is the same as what substitutability sounds like:
(def x 5)
(+ x 7)
-> 12
ie, (+ x 7) expands to, or is the same as, (+ 5 7)
What am I missing here?
After looking at this for a while, I'm starting to suspect that it has something to do with the fact that the if-method and if-route functions are actually private ((defn- if-route ...)).
Also, for macros, when you do the back-tick quote (" ` ") you are actually getting the fully-namespace-specified symbol in the final expansion:
`(+ 2 3)
would expand to
(clojure.core/+ 2 3)
Since these methods are private, they won't be accessible in the normal expansion, therefore the var function is used, to get to the symbol that holds a reference to the actual function that must be invoked at this point in the expansion.
ring-reload can reload var definitions from files that you keep modifying during development. Since you pass on a (var ...), it is resolved every time you try to read it, and as a consequence the reloaded vars can be re-read on every request. This leads to interactive web development (without needing to compile etc.) If you don't use (var ...) and rather pass the value directly then the reloaded vars will not be passed to the ring URI handlers and hence you cannot simply modify-and-run your code.
Check this blog entry for example:
http://charsequence.blogspot.com/2010/09/interactive-web-development-with.html
I have a Clojure program that I build as a JAR file using Maven. Embedded in the JAR Manifest is a build-version number, including the build timestamp.
I can easily read this at runtime from the JAR Manifest using the following code:
(defn set-version
"Set the version variable to the build number."
[]
(def version
(-> (str "jar:" (-> my.ns.name (.getProtectionDomain)
(.getCodeSource)
(.getLocation))
"!/META-INF/MANIFEST.MF")
(URL.)
(.openStream)
(Manifest.)
(.. getMainAttributes)
(.getValue "Build-number"))))
but I've been told that it is bad karma to use def inside defn.
What is the Clojure-idiomatic way to set a constant at runtime? I obviously do not have the build-version information to embed in my code as a def, but I would like it set once (and for all) from the main function when the program starts. It should then be available as a def to the rest of the running code.
UPDATE: BTW, Clojure has to be one of the coolest languages I have come across in quite a while. Kudos to Rich Hickey!
I still think the cleanest way is to use alter-var-root in the main method of your application.
(declare version)
(defn -main
[& args]
(alter-var-root #'version (constantly (-> ...)))
(do-stuff))
It declares the Var at compile time, sets its root value at runtime once, doesn't require deref and is not bound to the main thread. You didn't respond to this suggestion in your previous question. Did you try this approach?
You could use dynamic binding.
(declare *version*)
(defn start-my-program []
(binding [*version* (read-version-from-file)]
(main))
Now main and every function it calls will see the value of *version*.
While kotarak's solution works very well, here is an alternative approach: turn your code into a memoized function that returns the version. Like so:
(def get-version
(memoize
(fn []
(-> (str "jar:" (-> my.ns.name (.getProtectionDomain)
(.getCodeSource)
(.getLocation))
"!/META-INF/MANIFEST.MF")
(URL.)
(.openStream)
(Manifest.)
(.. getMainAttributes)
(.getValue "Build-number")))))
I hope i dont miss something this time.
If version is a constant, it's going to be defined one time and is not going to be changed you can simple remove the defn and keep the (def version ... ) alone. I suppose you dont want this for some reason.
If you want to change global variables in a fn i think the more idiomatic way is to use some of concurrency constructions to store the data and access and change it in a secure way
For example:
(def *version* (atom ""))
(defn set-version! [] (swap! *version* ...))