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
Related
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!
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'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.
I've been trying to learn ClojureScript and stumbled upon some very mysterious function names.
For example:
(.-length str)
From the om docs:
(defn add-contact [data owner]
(let [new-contact (-> (om/get-node owner "new-contact")
.-value ;;What is this?
parse-contact)]
(when new-contact
(om/transact! data :contacts #(conj % new-contact)))))
What is that .- trying to indicate?
These are retrieving native JavaScript properties. Thus, (.-length str) would compile to the JavaScript str.length.
Contrast this to the ClojureScript (.length str), which would compile to the method invocation str.length() -- a rather different thing.
In the om case given, the code is doing the following in order:
Calling get-node, and taking its result
Taking the value property of that result
Calling the function parse-contact with that value passed.
This is because the threading macro, ->, substitutes the results of each stage as the first argument of the next -- making that code equivalent to (parse-contact (.-value (om/get-node owner "new-contact"))).
I have a lein project (using cascalog--but that's not particularly important). I'm trying to externalize properties like paths to files, so I end up with code that looks something like this:
(defn output-tap [path] (hfs-textline (str (get-prop :output-path-prefix) path) :sinkmode :replace))
(def some-cascalog-query
(<- [?f1 ?f2 ?f3]
((output-tap (get-prop :output-path)) ?line)
(tab-split ?line :> ?f1 ?f2 ?f3)))
In the example above, assume the function get-prop exists; it's just using standard java to read a property value (based off this example: loading configuration file in clojure as data structure).
Now I have a main method that loads the property values, e.g. something like:
(defn -main [& args] (do (load-props (first args)) (do-cascalog-stuff)))
But when I lein uberjar I get a compile time error saying:
Caused by: java.lang.IllegalArgumentException: Can not create a Path from an empty string
at org.apache.hadoop.fs.Path.checkPathArg(Path.java:82)
at org.apache.hadoop.fs.Path.<init>(Path.java:90)
at cascading.tap.hadoop.Hfs.getPath(Hfs.java:343)
Are defs always compile time evaluated (rather than runtime evaluated)? Or am I misunderstanding this error?
So, you want the property lookup to occur at run-time? Then yes, you'll need to define some-cascalog-query as a function or macro. A bare def causes the expression to be evaluated when the code is loaded, not when the var is dereferenced.
This can be illustrated pretty simply in the REPL:
user=> (def foo (do (println "Hello, world!") 1))
Hello, world!
#'user/foo
user=> foo
1
From the documentation (emphasis mine):
(def symbol init?)
Creates and interns or locates a global var with the name of symbol and a namespace of the value of the current namespace (ns). If init is supplied, it is evaluated, and the root binding of the var is set to the resulting value.
that error looks like (get-prop :output-path) (get-prop :output-path-prefix) are is returning nothing which is getting wrapped into an empty string by str. perhaps the property is not being found?
does get-prop work as expected?
your understanding of defs is correct, they are are compile time, not (usually) runtime.