In a file i define these 2 macros:
(ns macros)
(defmacro foo [a]
`(+ ~a 2))
(defmacro bar [a]
`(* 2 (foo ~a)))
In clojure both macros work as intended.
In clojurescript only the macro "foo" works, "bar" produces this error:
"Error evaluating:" (bar 0) :as "(2 * macros.foo.call(null,0));\n"
org.mozilla.javascript.EcmaError: ReferenceError: "macros" is not defined. (<cljs repl>#4)
at <cljs repl>:4 (anonymous)
at <cljs repl>:4
It seems that here the "foo" macro gets not expanded but interpreted as a function call.
Ist this a bug in clojurescript or did i something wrong?
I believe the issue you're seeing here is due to the single element namespace for the macros file. If you change it to util.macros and put in the proper place on the classpath to account for that, it works.
Probably a bug given it works without issue in Clojure.
Related
Not sure if valid question, but i'm learning macros and i'm trying to write a macro (for clojurescript but should be same thing) so i can do nicer js/require in node.
The syntax will look like this:
(import ["some-module" :as module1]
["some-other-module" :as module2])
and it would expand to this:
(do
(def module1 (js/require "some-module")
(def module2 (js/require "some-module"))
My question is:
Is it ok to do 'def' inside a do block?
cljs does not seem to complain, but is it ok from a macro design stand point?
Yes, using the (do (def ...) (def ...)) pattern is generally the only way to def multiple things in a macroexpansion.
If you run the following it only prints "foo":
(if true (println "foo") (println "bar"))
;foo
However if you pass macros in as the arguments to the if, it seems to evaluate both macros immediately.
(defmacro foo
[]
(println "foo"))
(defmacro bar
[]
(println "bar"))
(if true (foo) (bar))
;foo
;bar
How do you avoid running both macros and just evaluate the one for the true condition?
EDIT:
The main source of my confusion is that this would work in common lisp. I don't know how common lisp handles compiling macros differently but I'm guessing it has to do with more freedom not being on the JVM.
To clarify the actual code was to create forms of a certain type without quoting them as arguments. The code was being iterated on and was going to get more complicated, but in the current state was along the lines of:
(defmacro foo
[arg1 arg2]
`(quote (~arg1 ~arg2 [])))
(defmacro bar
[arg1 arg2]
`(quote (~(first arg1) ~arg2 [~(second arg1)])))
(defmacro foobar
[arg1 arg2]
`(if (list? '~arg1)
(bar ~arg1 ~arg2)
(foo ~arg1 ~arg2)))
(foobar FOO "bar")
;; doesn't work since macros get compiled and you can't pass FOO as an argument to bar
(foobar (FOO "bar") "foobar")
;; (FOO "bar" ["foobar"])
I wanted both macros to not be expanded before evaluating the if since passing something other than a list to bar would cause an exception. I now understand that's not possible because expansion happens compile time. I've switched to using multimethods--which is more verbose, but more polymorphic I suppose.
Alan has the right of it (in terms of the immediate fix needed), but to speak to the reasoning:
Macros are evaluated at compile time, not runtime. It's patently impossible for something only known at runtime to control what's compiled, because all compilation is necessarily finished before runtime starts.
What you can do is make your if part of another macro, thus moving it to compile time as well.
You forgot the "syntax quote". The code should look like this:
(defmacro foo
[]
`(println "foo"))
(defmacro bar
[]
`(println "bar"))
(if true
(foo)
(bar))
;=> foo
Macros are abstraction on syntax. You use it when you see a pattern you often write, but because of argument evaluation you cannot use functions. Macros evaluate to code and there should not be side effects since you have no control over when it gets expanded (run).
foo and bar should have been functions. Then it will work as you intended.
(defn foo
[]
(println "foo"))
(defn bar
[]
(println "bar"))
(if true
(foo)
(bar)) ; prints "foo"
Using a macro when it's not needed is considered bad practice.
I get some weird behaviour when checking if a symbol can be resolved.
user=> ok
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ok in this context, compiling:(NO_SOURCE_PATH:0)
user=> (resolve 'ok)
nil
user=> (if (resolve 'ok) "bla" (def ok 'ok))
"bla"
user=> ok
#<Unbound Unbound: #'user/ok>
user=> (def ok 'ok)
#'user/ok
user=> ok
ok
Can anyone tell me where this might come from? Is this behaviour intended?
(def ok "whatever") creates a variable named ok at compile time. The compiler scans the whole form to compile it, discovers that you will be defining a var named ok, and creates it for you (with no binding), before your form is actually executed. When the def form is actually executed, the runtime value of the expression will be assigned to the var user/ok. In your example, this never happens, because the var has already been created, and the if branch goes the other way.
Using bound? as a substitute is a terrible idea, as it tests something quite different: whether the named var (which must exist) has a binding, either permanent or thread-local.
Since I only use it inside a macro I now use it as follows
(defmacro bla [x]
(if (resolve x) x `(def ~x '~x)))
And now it works since def is inside the quoted form and evaluated after resolve.
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.
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.