What does ^:dynamic do in Clojure? - clojure

I've googled for "clojure dynamic" and "clojure dynamic scope" and read over 10 articles and I still don't have a clear understanding of what ^:dyanmic does. I think this article may be answering my question, but the code samples seem to be "missing" so I'm not even sure if it's referring to the same thing I'm confused about.
I'm trying to fix an issue in the clj-http project but first I have to understand the code. It has functions defined like this:
(defn ^:dynamic parse-html
"Resolve and apply crouton's HTML parsing."
[& args]
{:pre [crouton-enabled?]}
(apply (ns-resolve (symbol "crouton.html") (symbol "parse")) args))
But I don't understand what that ^:dynamic means/does. Can anyone explain it to me in a really simple way?

It is defining the function as being dynamically scoped.
In other words, this allows someone to re-bind parse-html in a given function invocation and have that new binding apply only to functions called from that specific invocation.
If parse-html were not dynamically scoped then re-binding it would cause the new binding to be seen by any code that uses parse-html and not just code that was activated by the function invocation that did the re-binding.
Dynamic scoping is useful as a substitute for globally scoped variables. A function can say "let current_numeric_base = 16; call other functions;" and the other functions will all print in hexadecimal. Then when they return, and the base-setting function returns, the base will return to whatever it was.
http://c2.com/cgi/wiki?DynamicScoping
As was pointed out in the comments below, you can't actually re-bind variables that aren't dynamically scoped in Clojure. If you could, updating a variable that is lexically scoped will impact all code that is executed even if it is running in a different call stack from where the re-bind occurred.
So maybe some pseudo-code will make the difference between dynamic and lexical scope clear.
Example of using a dynamically scoped variable:
(def ^:dynamic a 0)
(defn some-func [x] (+ x 1))
; re-binds a to 1 for everything in the callstack from the (binding)
; call and down
(binding [a 1]
(print (some-func a)))
; a was only re-bound for anything that was called from
; within binding (above) so at this point a is bound to 0.
(print (some-func a))
would print:
2
1
Example of a lexically scoped variable:
(def a 0)
(defn some-func [x] (+ x 1))
; re-binds a to 1 for everyone, not just things that
; are in the callstack created at this line
(set-var [a 1] ; set-var is a made up function that can re-bind lexically scoped variables
(print (some-func a)))
; a was lexically scoped so changing it changed
; it globally and not just for the callstack that
; contained the set-var.
(print (some-func a))
would print:
2
2

Related

Clojure with-local-vars in closure

In Clojure, are the variables defined through with-local-vars accessible through closure?
Consider the below example:
(defn foo []
(with-local-vars [bar 10]
(fn [] #bar)))
((foo))
Result is the following:
#object[clojure.lang.Var$Unbound 0x131f68d8 "Unbound: #<Var: --unnamed-->"]
(Instead, I was expecting to get 10.)
C.f. with the following:
(defn foo []
(with-local-vars [bar 10] #bar))
(foo)
Result: 10.
Based on the documentation, it is not clear to me, if it is valid to use local vars in Clojure as above, but I would suspect the answer is no. Can you please confirm this (or refute, and explain what I'm doing wrong in the first example)? And if my supposition is clear (i.e., that local vars cannot be used in the closure), then explain what is the reason for that?
EDIT: for the records, this is the problem I was trying to solve.
The documentation for with-local-vars doesn't seem particularly clear here. It just says it creates thread-local bindings for the variables, but doesn't say anything about what happens to them when you exit the with-local-vars scope.
In contrast, the with-bindings documentation explicitly says that the thread-local bindings are popped when leaving that scope.
If you look at the source code, you can see that both with-local-vars and with-bindings are implemented using the same basic mechanisms (pushThreadBindings and popThreadBindings), which suggests they should have almost identical behavior.
So yes, you're right, you cannot expect the with-local-vars values captured in a closure to work outside of the with-local-vars scope. However, Clojure provides the bound-fn mechanism specifically for building this type of closure, capturing all of the current thread-local bindings:
(def foo (with-local-vars [bar 10] (fn [] #bar)))
(foo)
; => #object[clojure.lang.Var$Unbound 0x60063e12 "Unbound: #<Var: --unnamed-->"]
(def baz (with-local-vars [bar 10] (bound-fn [] #bar)))
(baz)
; => 10

In Clojure how to define a global variable which can be accessed from other name space

In clojure, What is the best possible way to declare a global variable, the value of which needs to be changed in a function and this global variable need to be accessed in other namespaces
Ex:
(ns ..main
.....)
(def global_variable nil)
..
(defn main ...
Change the value of global variable here
)
Another name space
(ns accessvariable ...)
(println (main/global_variable))
What is the best way to do this?
Just store an atom in your global var:
(def global-var (atom nil))
Note: this is in response to the third comment on the question. dAni's answer applies to the question as asked.
Idiomatic Clojure favors functions whose outputs are determined only by their input parameters. This is in contrast to a function which relies on its parameters and global state, too. It is easy to convert a function which uses global data into one that does not - you just need to add a parameter that will contain the data. For example: instead of (defn print-global [] (println #global-atom-defined-elsewhere)), you use (defn print-my-val [val] (println val)).
If you use the command line argument extremely frequently, you might still find it more convenient to put the data in a global atom, instead of having everything use it as a parameter. This is up to you.

How can I prevent symbol contamination between Clojure tests?

I use simulation-style tests in to ensure that my entire application works correctly. The core Clojure test library is used for tests, executed via Leiningen. As the -main function runs, it defines symbols for later use within its logic. The problem is that if I accidentally use a symbol created in one -main test but never defined in the current -main test, it still has a value. I would expect to get an error that the symbol is undefined, but it seems my test environment is somehow sharing state between deftest executions. How can I deal with this? Move all my convenience-driven symbol definitions to a let statement?
If you are def-ing global vars inside your function, that's generally considered bad practice and reason enough to use let as you suggest instead.
However, you can capture a snapshot the mappings of your namespace.
(def ns-snapshot (ns-map *ns*))
So that after you intern symbols
(def foo 1)
(def bar 2)
You can determine the additions
(reduce dissoc (ns-map *ns*) (keys ns-snapshot))
;=> {bar #'so.core/bar, foo #'so.core/foo}
And un-map them
(doseq [[k v] (reduce dissoc (ns-map *ns*) (keys ns-snapshot))] (ns-unmap *ns* k))
So that you'll get the desired undefined error again
foo ;=> CompilerException ... Unable to resolve symbol: foo in this context

Clojure : Determine if a variable is declared

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.

Avoid overriding variable names

On a particular namespace I am working on I am beginning to run out of function names. Is there a way to get a warning like the one I get if I override a symbol from another namespace if I reuse a symbol which is already bound to a function in the same namespace?
If this is enough of a problem that you'd be willing to replace a (set of) core macro(s), you could try this approach:
(ns huge.core
(:refer-clojure :exclude [defn]))
(defmacro defn [name & defn-tail]
(assert (nil? (resolve name))
(str "Attempting to redefine already defined Var "
"#'" (.name *ns*) "/" name))
`(clojure.core/defn ~name ~#defn-tail))
Then any attempt to redefine an existing Var with defn will fail:
user=> (defn foo [] :foo)
#'user/foo
user=> (defn foo [] :bar)
AssertionError Assert failed: Attempting to redefine already defined Var #'user/foo
(nil? (resolve name)) user/defn (NO_SOURCE_FILE:2)
You could similarly replace defmacro; in that case you would have to call clojure.core/defmacro when defining your own variant.
Plain, unadorned def is a special form and receives magic treatment from the compiler, so you could still overwrite existing Vars with it. If you would like to guard against name clashes on that flank too, you could switch to something like defvar (used to be available in clojure.contrib.def) with a similar custom assert.
This isn't quite an answer to your question but may help avoid the issue depending on how the functions in your namespace are being used. You could make them into local functions using letfn, allowing you to reuse names for functions that are only used within the context of another function.
(defn main-fn [x]
(letfn [(secondary-fn [x] (* x x))
(another-fn [x] (secondary-fn (inc x)))]
(/ (another-fn x) 4)))
Even if you restrict yourself to single-character function names, you are in no danger of running out, as there are (about) 64 thousand Unicode characters, any one of which is a valid function name.
Given that you can in fact have names that are ten thousand characters long, you are on even safer ground.