checking symbol equality in defmacro (clojure) - clojure

This returns false.
(defmacro scratch [pattern]
`(= 'b (first ~pattern)))
(scratch '(b))
However, the output of the following is b.
(defmacro scratch2 [pattern]
`(first ~pattern))
(scratch2 '(b))
How do I setup the first macro to return true?

that is happening, because the 'b that you introduce in macro is namespaced:
example:
user> (defmacro nsmac []
`(namespace 'b))
user> (nsmac)
;;=> "user"
while the value you pass isn't:
user> (namespace (first '(b)))
;;=> nil
so, you can pass the namespaced symbol to a macro, like this:
user> (scratch '(user/b))
;;=> true
or you can fix you macro to use unnamespaced symbol (known trick with qoute-unquote):
(defmacro scratch [pattern]
`(= '~'b (first ~pattern)))
user> (scratch '(b))
;;=> true
but what you really want, is to check this one in compile-time, because this macro you have is better as a plain function, since it doesn't employ any macro-related goodness.
It could look like this:
(defmacro scratch [pattern]
(= 'b (first pattern)))
(scratch (b))
;;=> true
something about namespacing can be found in this article

Related

working with non-namespaced symbols in clojure

Here's a working minimal example showing how Clojure can handle non-namespaced symbols:
(defmacro simple-macro [s]
(name `~s))
(str "And the answer is "
(simple-macro v1))
Now I'd like to do something more complicated. Inspired by this example:
(defn typical-closure []
(let [names (atom [])]
(fn [arg] (swap! names conj arg) #names)))
(def Q (typical-closure))
(Q 1)
(Q 2)
;; [1 2]
I now want to define a similar closure to take the names of undefined variables.
(defn take-names-fun []
(let [names (atom [])]
#((swap! names conj (simple-macro %)) (deref names))))
(def P (take-names-fun))
(P v1)
But this doesn't work as hoped; I get the error:
Unable to resolve symbol: v1 in this context
Is there a way to fix this so that we can add the name "v1" to the list of names defined above?
I tried using a macro instead (inspired by a syntax trick on page 21 of "Mastering Clojure Macros")... but this answer on ask.clojure.org says it doesn't make sense to define a closure over an atom in a macro.
(defmacro take-names-macro []
(let [names (atom [])]
`(fn [~'x] (swap! ~names conj (simple-macro ~'x)) (deref ~names))))
(def R (take-names-macro))
And indeed, I get another error here:
Can't embed object in code, maybe print-dup not defined:
However, there is no such restriction for using atoms inside defn. Maybe at the end of the day I need to put my symbols in a namespace...?
Not quite sure what it is that you're ultimately trying to accomplish.
But, since P is a function, it will always evaluate its arguments. So, if you pass it an undefined symbol, you'll get the error you got. Instead, you have to create a macro so that you can quote the undefined symbol (to stop the evaluation of the argument) and then pass that to P. Here is an example that does that.
user> (defn take-names-fun []
(let [names (atom [])]
(fn [arg] (swap! names conj (name arg)))))
#'user/take-names-fun
user> (def P (take-names-fun))
#'user/P
user> (defmacro PM [s] `(P (quote ~s)))
#'user/PM
user> (PM v1)
["v1"]
user> (PM v2)
["v1" "v2"]
user>
You might find the article on Evaluation in Clojure helpful.
#dorab's answer is nice.
But you could also tell yourself: "When entering undefined variables into a function, I have to quote them to avoid evaluation of them!"
So, after:
(defn typical-closure []
(let [names (atom [])]
(fn [arg] (swap! names conj arg) #names)))
(def Q (typical-closure))
Do:
user=> (Q 'v1)
[v1]
user=> (Q 'v2)
[v1 v2]
user=> (Q 3)
[v1 v2 3]
user=> (Q 'v4)
[v1 v2 3 v4]
user=>
In this way you don't need the macro and you can alternate between evaluated and not-evaluated arguments (undefined symbols).
So with the way fn's are written in clojure there is unfortunately no way to get the name of the var being passed as a param from within the fn body.. Someone with more experience with the clojure src may be able to explain better why that is, my initial guess would be that it has something to do with keeping thread local scopes isolated and lazy.
But there's absolutely nothing stopping you from writing a macro that wraps other macros using your closure idea!
Here's an example of how something like that may be written:
https://stackoverflow.com/a/11857444

Clojure caret as a symbol?

So I thought it would be a nice idea to name a function that calculates the exponential ^, but it seems like the caret actually does something special, as the Clojure REPL generates an error when evaluating '^. Googling mostly gave me this, so I was wondering what the actualy use for the caret in Clojure is.
(Also, would it be possible after all to name a function ^?)
^ is "the meta character" it tells the reader to add the symbol starting with ^ as metadata to the next symbol (provided it is something that implements IMetas)
user=> (def x ^:IamMeta [1 2 3])
#'user/x
user=> x
[1 2 3]
user=> (meta x)
{:tag :IamMeta}
user=>
You can learn a lot about how clojure works under the hood by looking at the meta of things, for instance functions:
user=> (meta foo)
{:ns #<Namespace user>,
:name foo, :file "NO_SOURCE_PATH",
:line 5, :arglists ([s])}
this is very often used for type hints
(defn foo [^String s] (.charAt s 1))
it is generally a good idea to turn on reflection warnings (set! *warn-on-reflection* true) and then add type hints until the warnings go away. without these Clojure will look up the type of the function operands at run-time, which saves you the trouble of fussing with types though at a slight cost.
PS: My next favorite reader character is the "dispatch" character #, it is well worth learning about it next :)
PPS: this is different in clojure 1.2.x vs clojure 1.3.x
in Clojure 1.2.1 metadata does not compose when you use the meta-character:
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:tag :foo}
and in 1.3 it "does the right thing" and also keywords are options instead of "tags":
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}
It seems to me that the answer to your question is, unfortunately, no. In Clojure, you cannot name a function ^.
I tried the following in the REPL:
user=> (println \^)
^
nil
This seems to imply that you can escape the carat (^) with a backslash. However, if I try to declare a function using \^ as a name then I get an error message:
user=> (defn \^ [n e] (cond (= e 0) 1 :else (* n (\^ n (- e 1)))))
IllegalArgumentException First argument to defn must be a symbol
clojure.core/defn (core.clj:277)
The same code works with a regular text name:
user=> (defn exp [n e] (cond (= e 0) 1 :else (* n (exp n (- e 1)))))
#'user/exp
user=> (exp 3 3)
27
I would be delighted if someone with better Clojure-fu than mine could prove me wrong! :)

Converting a string into a function that is not in a namespace in clojure

Here is the sample code I want to get to work:
(letfn [(CONC [f] f)
(CONT [f] (str "\newline" f))]
((voodoo "CONC") "hamster"))
Is there some voodo that will make it call the CONC function with hamster as the parameter? That is, is there some way to convert the string "CONC" into a function that is not bound to a namespace but rather to a local binding?
EDIT:
To be clearer, the way this will be called is:
(map #((voodoo (:tag %)) (:value %))
[
{:tag "CONC" :value "hamster"}
{:tag "CONT" :value "gerbil"}
]
)
I'd probably solve this by creating a map of functions indexed by strings:
(def voodoo
{"CONC" (fn [f] f)
"CONT" (fn [f] (str "\newline" f))})
Then your desired code should work directly (exploiting the fact that a map is a function that looks up it's argument)
(map #((voodoo (:tag %)) (:value %))
[
{:tag "CONC" :value "hamster"}
{:tag "CONT" :value "gerbil"}
]
)
Note that the functions here are fully anonymous - you don't need them to be referenced anywhere in the namespace for this to work. In my view this is a good thing, because unless you also need the functions somewhere else then it's best to avoid polluting your top-level namespace too much.
No. Eval does not have access to the local/lexical environment, ever.
Edit: This is not a very good answer, and not really accurate either. You could write voodoo as a macro, and then it doesn't need runtime access to the lexical environment, just compile-time. However, this means it would only work if you know at compile time that the function you want to call is x, and so it wouldn't be very useful - why not just type x instead of (voodoo "x")?
(defmacro voodoo [fname]
(symbol fname))
(letfn [(x [y] (inc y))]
((voodoo "x") 2))
;; 3
(letfn [(x [y] (inc y))]
(let [f "x"]
((voodoo f) 2)))
;; error
Well, it's sort of possible:
(defmacro voodoo [s]
(let [env (zipmap (map (partial list 'quote) (keys &env))
(keys &env))]
`(if-let [v# (~env (symbol ~s))]
v#
(throw (RuntimeException. "no such local")))))
...and now we can do weird stuff like this:
user> (defn example [s]
(letfn [(foo [x] {:foo x})
(bar [x] {:bar x})]
((voodoo s) :quux)))
#'user/example
user> (example "foo")
{:foo :quux}
user> (example "bar")
{:bar :quux}
user> (example "quux")
; Evaluation aborted.
user> *e
#<RuntimeException java.lang.RuntimeException: no such local>
That "Evaluation aborted" means an exception was thrown.
You could also replace the throw branch of the if in voodoo with (resolve (symbol ~s)) to defer to the globals if no local is found:
(defmacro voodoo [s]
(let [env (zipmap (map (partial list 'quote) (keys &env))
(keys &env))]
`(if-let [v# (~env (symbol ~s))]
v#
(resolve (symbol ~s)))))
...and now this works with definition of example as above (though note that if you are experimenting at the REPL, you will need to recompile example after redefining voodoo):
user> (defn quux [x] {:quux x})
#'user/quux
user> (example "quux")
{:quux :quux}
Now, this is an abuse of Clojure's facilities which one would do well to try to do without. If one cannot, one should probably turn to evalive by Michael Fogus; it's a library which provides an "eval-with-locals" facility in the form of an evil function and a couple of utilities. The functionality seems to be well factored too, e.g. something like the ~(zipmap ...) thing above is encapsulated as a macro and evil there appears to be almost a drop-in replacement for eval (add the env parameter and you're good to go). I haven't read the source properly, but I probably will now, looks like fun. :-)
Im not really clear what you are asking for so i'll try a couple answers:
if you have a string that is the name of the function you wish to call:
(def name "+")
((find-var (symbol (str *ns* "/" name))) 1 2 3)
this would give voodoo a deffinition like this:
(defn voodoo [name args] (apply (find-var (symbol (str *ns* "/" name))) args))
#'clojure.core/voodoo
clojure.core=> (voodoo "+" [1 2 3])
6
clojure.core=>
this assumes your function is in the current namepace ns.
if you want to turn a string into a function you could use this pattern
(let [f (eval (read-string "(fn [] 4)"))] (f))

Clojure macro evaluation of strings

I am trying to create a clojure macro that converts an entered symbol to a string. However, when I do this:
(defmacro convert-to-string [something]
`(call-converted "~something")
)
(macroexpand '(convert-to-string convert-this))
: I get :
(call-converted "~something")
: instead of :
(call-converted "~convert-this")
: does anyone show me how I could do this?
You might consider using keywords (or quoted symbols) and a function, rather than a macro:
(defn convert-to-string [x] (call-converted (name x)))
(convert-to-string :foo)
(convert-to-string 'foo)
If you really want a macro:
(defmacro convert-to-string [x] `(call-converted ~(name x)))
(macroexpand-1 '(convert-to-string foo))
=> (user/call-converted "foo")
I am in no way an expert on macros, but would this solve your problem:
(defmacro to-str [expr] (str expr))

Clojure coalesce function

SQL offers a function called coalesce(a, b, c, ...) that returns null if all of its arguments are null, otherwise it returns the first non-null argument.
How would you go about writing something like this in Clojure?
It will be called like this: (coalesce f1 f2 f3 ...) where the fi are forms that should only be evaluated if required. If f1 is non-nil, then f2 should not be evaluated -- it may have side-effects.
Maybe Clojure already offers such a function (or macro).
EDIT: Here a solution that I came up with (modified from Stuart Halloway's Programming Clojure, (and ...) macro on page 206):
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if c# c# (coalesce ~#rest)))))
Seems to work.
(defmacro coalesce
([] nil)
([x] x)
([x & rest] `(let [c# ~x] (if (not (nil? c#)) c# (coalesce ~#rest)))))
Fixed.
What you want is the "or" macro.
Evaluates exprs one at a time, from left to right. If a form
returns a logical true value, or returns that value and doesn't
evaluate any of the other expressions, otherwise it returns the
value of the last expression. (or) returns nil.
http://clojuredocs.org/clojure_core/clojure.core/or
If you only want nil and not false do a rewrite of and and name it coalesce.
Edit:
This could not be done as a function because functions evaluate all their arguments first. This could be done in Haskell because functions are lazy (not 100% sure about the Haskell thing).
Based on nickik's answer and "or" clojure macro:
(defmacro coalesce
([] nil)
([x] x)
([x & next]
`(let [v# ~x]
(if (not (nil? v#)) v# (coalesce ~#next)))))
You could use keep introduced in 1.2:
EDIT: extended answer a little bit. Macro for direct invokations. Helper for eg. apply + lazy seq producing the values.
(defn coalesce*
[values]
(first (keep identity values)))
(defmacro coalesce
[& values]
`(coalesce* (lazy-list ~#values)))
However to prevent evaluation of the values one needs some home-grown way.
Ugly:
(lazy-cat [e1] [e2] [e3])
A little more involved but prettier in the code:
(defn lazy-list*
[& delayed-values]
(when-let [delayed-values (seq delayed-values)]
(reify
clojure.lang.ISeq
(first [this] #(first delayed-values))
(next [this] (lazy-list* (next delayed-values)))
(more [this] (or (next this) ())))))
(defmacro lazy-list
[& values]
`(lazy-list* ~#(map (fn [v] `(delay ~v)) values))
Some function versions of coalesce, if you'd rather avoid macros:
(defn coalesce
"Returns first non-nil argument."
[& args]
(first (keep identity args)))
(defn coalesce-with
"Returns first argument which passes f."
[f & args]
(first (filter f args)))
Usage:
=> (coalesce nil "a" "b")
"a"
=> (coalesce-with not-empty nil "" "123")
"123"
Unlike the spec, this will evaluate all args. Use or or another appropriate macro solution if you want short circuiting evaluation.
Perhaps I'm misapprehending the question, but isn't this just the first filtered element?
E.g.:
user=> (first (filter (complement nil?) [nil false :foo]))
false
user=> (first (filter (complement nil?) [nil :foo]))
:foo
user=> (first (filter (complement nil?) []))
nil
user=> (first (filter (complement nil?) nil))
nil
It could be shortened up to:
(defn coalesce [& vals]
(first (filter (complement nil?) vals)))
user=> (coalesce nil false :foo)
false
user=> (coalesce nil :foo)
:foo
user=> (coalesce nil)
nil
user=> (coalesce)
nil