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
Related
I'm studing macros and as project example building an route system. An route (functions get/post/put/...) can be attached to an scope, when it occurs the route url is prefixed by the actual scope, example:
;; base scope macro
(defmacro scope [url & body]
`(let [~'base-scope ~url
~'get #(str ~'base-scope %)]
~#body))
(scope "admin/"
(get "stackoverflow")) ;; OK! returns 'admin/stackoverflow'
The problem is that scope can be nested:
(scope "admin/"
(scope "api/"
(get "stackoverflow")))
My question is: How can I make a lookup under the actual scope, searching for route prefixes(scopes)? I know that I have access to &env and &form implicits; should I use &env and try to create a kind of hidden prefixes, or use &form?
One option would be to use dynamic bindings – have a Var initially bound to [] and conj scopes on to it in scope-emitted binding forms. Overall it should be pretty straightforward, and also limited in some ways – you'd have to be careful about the dynamic extent / lifetime of your bindings.
If you're after something lexically scoped, you could use tools.macro's local macros to redefine scope invocations nested within other scope invocations. (In that case I would factor out as much of the actual logic into a helper function or two.)
As a very straightforward alternative, you could introduce a distinguished local name – preferably generated using gensym – and use it in scope's expansion much like the dynamic binding of the distinguished Var in the approach described above. The difference is that here the scopes would actually be lexically scoped. There's at least one caveat in that evil user code in the body could access or shadow the distinguished local – it's pretty unlikely with a gensym, though not that difficult if one feels like breaking things. The key point, though, is that one might be justified in feeling uncomfortable about "globally magic locals".
Finally, you could also introduce fresh "locally magic locals" in each expansion and search for them in &env. Here's a simple proof of concept using metadata to mark the magic locals:
(defmacro scope [sname & body]
(let [scopes (filterv #(contains? (meta %) :scope) (keys &env))
maybe-printout (if (seq scopes)
[(list* `println scopes)])]
`(let [~(with-meta (gensym "scope__") {:scope true}) '~sname]
~#maybe-printout
~#body)))
At the REPL,
(scope :foo
(scope :bar
(scope :quux
(scope :xyz))))
prints out
:foo
:foo :bar
:foo :bar :quux
returning nil.
(set! *print-meta* true) and a macroexpand call reveal that the above expands to
(let* [^{:scope true} scope__16668 (quote :foo)]
^{:line 4, :column 6}
(scope :bar
^{:line 5, :column 8}
(scope :quux
^{:line 6, :column 10}
(scope :xyz))))
Of course only the :scope metadata is interesting. If it's ok to assume that scope names must be compile-time constants, it's even possible to retrieve their actual values at compile time (see clojure.lang.Compiler$LocalBinding and clojure.lang.Compiler$ConstantExpr), but that'd be an unnecessary hack in this case.
This doesn't solve the whole problem as written – rather than creating new individual "scope locals", scope should probably maintain locals with growing vectors of scope names to preserve ordering. This can be done e.g. by searching for a :scope-tagged local and shadowing it if it exists (if not, we're in a top-level scope and a new local should be created).
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
;; Once upon a time I opened a REPL and wrote a protocol
;; definition:
(defprotocol SomeProtocol
(f [this]))
;; And a record:
(defrecord SomeRecord []
SomeProtocol
(f [this]
"I don't do a whole lot."))
;; And a very useful side-effect free function!
(defn some-function []
(f (SomeRecord.)))
;; I call my function...
(some-function)
;; ...to see exactly what I expect:
;; user=> "I don't do a whole lot."
;; Unsatisfied with the result, I tweak my record a little bit:
(defrecord SomeRecord []
SomeProtocol
(f [this]
"I do a hell of a lot!"))
(some-function)
;; user=> "I don't do a whole lot."
Looks like a bug to me. I just cannot be sure after having seen so
many false compiler bug reports in c++ user group.
You need to re-define the some-function after redefining the record again. The reason for this is that defrecord creates a new type (using deftype) and using the (SomeRecord.) notation inside the function will bind the code to that type even after a new type with same name is defined. This is why it is usually prefer to use (->SomeRecord) notation to instantiate the record, using this notation will make your code work like you expected.
I was reading Clojure in Action chapter 8 about TDD and experimented with the stubbing macro. It uses the dynamic binding mechanism to stub functions. Alas, in Clojure 1.3 it is not possible to use the binding mechanism for non-dynamic vars, so the stubbing macro doesn't work in most cases, unless you explicitly declare the var which points to a function dynamic. Then I wondered how stubbing is done in Midje and tried to find the source for 'provided', but I couldn't find it. So here it goes:
How is 'provided' implemented in a fact in Midje? Can someone explain this in detail?
Clojure 1.3 provides a with-redefs macro that works even with vars that haven't been declared dynamic:
user=> (def this-is-not-dynamic)
user=> (with-redefs [this-is-not-dynamic 900] this-is-not-dynamic)
900
For backward compatibility, Midje uses its own version, whose guts look like this:
(defn alter-one-root [[variable new-value]]
(if (bound? variable)
(let [old-value (deref variable)]
(alter-var-root variable (fn [current-value] new-value))
[variable old-value])
(do
(.bindRoot variable new-value)
[variable unbound-marker])))
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.