I'm creating a library for an API server, here's a simpliefied version of I have:
(defonce ^:dynamic *my-token* nil)
(defmacro def-my-token
[token1 & body]
`(binding [*my-token* ~token1] ~#body))
And the main "post" method:
(defn my-post-request [url1]
(try
(let [res (client/post (str "api/url/base" url1)
{:body (json/write-str (:secret my-token)) ; my-token should come from the macro
;......
And here's how I want to use it:
(defn -main [& args]
(def-my-token "fdsfdsfdsfds"
; now "my-token" should be created and visible in "my-post-request", shouldn't it?
(print
(my-post-request "/some_end_point"))))
But it says "Unable to resolve symbol: my-token in this context"
I wonder why? doens't def-my-token, being a macros, define it? why not? And how to fix that?
UPDATE:
Also without (defonce ^:dynamic *token* nil) it doesn't work. Why not?
Why isn't defining the macro enough?
Answer to your UPDATE:
According to the documentation for binding, you can only override already existing vars. That's why your solution doesn't work without establishing a root binding to your dynamic var.
Sidenote:
I would recommend doing what jmargolisvt said and use a plain def instead of defonce, as I've never seen any dynamic var definition in the wild using defonce.
EDIT:
doens't def-my-token, being a macros, define it? why not? And how to fix that?
Macros by themselves don't define things, they are small programs transforming your source code in the macro-expansion step of most Lisp REPL's. It could define anything you want it to, but then you should've wrote the def special form. What you used instead was binding which deals with already existing vars.
You might get more insight by toying with it in the REPL and/or reading the answer of this stackoverflow answer.
If you need some further explanation why overriding is needed:
It's practical to conceptualize vars as stacks. The root binding that you establish with using def is the first layer. Everything in your program will see this value unless you put "something" over it. As you can imagine in your example having *my-token* seen as nil from your functions would cause issues.
binding to the resuce!
It allows you put anything "on top" of the root binding (in your case nil) thread-locally inside of the body it, like so:
you bound *my-token*, not my-token. Try:
{:body (json/write-str (:secret *my-token*))
The asterisks are just a naming convention for dynamic vars, they are still part of the actual var name.
Related
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.
I have the following clojure code to initialize my config structure Config.
I noticed that the file is actually read when compiling the file, not at runtime.
For me, the config structure Config should be immutable, however, I do not want to have the configuration inside the JAR file.
How should I do this? Do I have to use an atom? It is okay if the application crashes if my.config is missing.
(def Config
(read-string (slurp "my.config")))
When you don't want it at compile time you have to wrap it in a function.
(defn def-my-conf []
(def Conf (blub)))
But you the cleaner way would be:
(declare Config)
(defn load-Config []
(alter-var-root (var Config) (blub)))
This function should be called inside your main.
EDIT: Of course an atom is also a solution!
Write a function for reading your config:
(defn read-config
[]
(read-string
(slurp "my.config")))
Then you can call this function from -main, and either 1) pass the config on to any functions that will need it, or 2) store it in a dynamic variable and let them read it directly:
(def ^:dynamic *config* nil)
(defn some-function-using-config
[]
(println *config*))
(defn -main
[]
(binding [*config* (read-config)]
(some-function-using-config)))
Which of the two to choose is a matter of taste and situation. With direct passing you make it explicit that a function is receiving config, with the dynamic variable you avoid having to include config as an argument to every single function you write, most of whom will just pass it on.
Both of these solutions work well for unit tests, since you can just rebind the dynamic variable to whatever config you want to use for each test.
TheQuickBrownFox had the answer, the file is read both at run-time, and a compile-time.
Fine for me! That is actually really cool!
While my lein new app project runs merrily inside the Light Table, lein uberjar won't work. Curiously, it behaves exactly like a classic Pascal compiler: it can't resolve references ahead of definitions. Another curiosity: yesterday it worked. I am not aware of fooling with anything sensitive.
Google says that the subj symptoms are quite commonplace; I tried whatever helped other people in the same (?) plight, but to no avail. By the way, usually they blame it on software bugs: "get the latest version of Leiningen and Clojure". I've got 2.5.0 and 1.6.
The project (main file) is here: https://github.com/Tyrn/pcc/blob/master/src/pcc/core.clj
As it is, parsed-args can't be resolved inside build-album; if I move the -main function to the top of the file, 'No such var' happens to cli-options inside -main. No amount of fiddling with explicit use of namespaces makes any difference.
Again, inside the Light Table everything runs fine.
Using def inside of a function is not idiomatic, especially if there is no reason to have it as a global variable. Just pass it as a function parameter:
(let [parsed-args (parse-opts ...)]
...
(build-album parsed-args))
If you really need global state, you can use e.g. a promise (alternatively, an atom):
(defonce parsed-args (promise))
...
(deliver parsed-args (parse-opts ...))
However, Clojure files are read from top to bottom, and yes, functions not having access to bindings introduced later in the file is by design. You can use declare to tell the parser what to expect:
(declare ^:dynamic *parsed-args*)
(defn build-album ...)
(def ^:dynamic *parsed-args* ...)
...
(binding [*parsed-args* (parse-opts ...)]
(build-album))
TL;DR: If not necessary, avoid global state; if necessary, minimize it.
I have a Clojure proxy statement that was getting large and messy, so I decided to try factoring the code of the beginDrag method redefinition out of the proxy statement, like this:
(defn enhanced-start-drag
""
[pie]
(let [pobj (. pie getPickedNode)
pobj-coll (seq (.. pie getInputManager
getKeyboardFocus getSelection))]
(println pobj)
(println pobj-coll)
(println "----------")
(proxy-super startDrag pie))) ; THIS IS LINE 94 (SEE ERROR MSG)
(defn custom-selection-event-handler [marqueeParent selectableParent]
(proxy [PSelectionEventHandler] [marqueeParent selectableParent]
(decorateSelectedNode [node]
(let [stroke-color (Color/red)]
(.setStrokePaint node stroke-color)))
(undecorateSelectedNode [node]
(let [stroke-color (Color/black)]
(.setStrokePaint node stroke-color)))
(startDrag [pie] ; pie is a PInputEvent
(enhanced-start-drag pie))
(endStandardSelection [pie] ; pie is a PInputEvent
(let [pobj (.getPickedNode pie)
slip (. pobj getAttribute "slip")
]
(swap! *last-slip-clicked*
(fn [x] slip))))))
I get the following compile error:
cd /Users/gw/tech/clojurestuff/cljprojects/infwb/src/infwb/
1 compiler notes:
Unknown location:
error: java.lang.Exception: Unable to resolve symbol: this in this context
core.clj:94:5:
error: java.lang.Exception: Unable to resolve symbol: this in this context
(core.clj:94)
Compilation failed.
As soon as I restore the body of enhanced-start-drag into the body of the proxy statement, everything works.
My question: Is there a way to move the messy details out to a separate function to improve the readability of my code?
Thanks for all your ideas and solutions.
UPDATE, 10/27/11: See the comments below. Arthur Ulfeldt was sharp in pointing out that the issue is captured references, and Dave Ray is also correct in saying that all you have to do is add this as a parameter to enhanced-start-drag and then proxy-super will work correctly. When I made the following two changes (without any changes to the body of enhanced-start-drag), my code was working again:
(defn enhanced-start-drag
""
[pie this]
and
(startDrag [pie] ; IN THE PROXY STMT IN custom-selection-event-handler
(enhanced-start-drag pie this))
BTW, my project uses Dave Ray's seesaw project to get a Java Swing UI. seesaw is awesome, as are its docstrings and sample code (which are much better than most commercial software). I highly recommend it! And thank you, Dave!
You have been bitten by symbol capture. In this case it is intentaional though you need to stay aware of it. From the doc for proxy-super
Use to call a superclass method in the body of a proxy method.
Note, expansion captures 'this`
proxy is creating a class that calls a function, when the call gets into enhanced-start-drag the value of this is not where proxy-super expects
you may needs to pass this as another argument into enhanced-start-drag and then call (. saved-this ...) instead of using proxy-super.
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* ...))