(defmacro test-failure
[& forms]
`(handler-case :type
~@forms
(~'handle :error/error
(println "error happened"))))
(My real macro is more complex, but this gives the idea.)
If I eval
(test-failure (println "test"))
I get:
=> Unable to resolve symbol: handle in this context
However, if I macroexpand-1 the thing, I get:
(macroexpand-1 '(test-failure (println "test")))
=> (clojure.contrib.condition/handler-case :type (println "test") (handle :error/error (clojure.core/println "error happened")))
That is correct, and if I eval just that it works fine.
Here is an interesting thing: if I do this:
(macroexpand '(test-failure (println "test")))
I get
=> (try (println "test") (handle :error/error (clojure.core/println "error happened")) (catch clojure.contrib.condition.Condition c__19__auto__ (clojure.core/binding [clojure.contrib.condition/*condition-object* c__19__auto__ clojure.contrib.condition/*condition* (clojure.core/meta c__19__auto__) clojure.contrib.condition/*selector* (:type (clojure.core/meta c__19__auto__))] (clojure.core/cond :else (clojure.contrib.condition/raise)))))
It's expanded the handler-case part, but the "handle" is still there. That seems wrong to me.
I've tried lots of different ways to specify handle besides ~'handle, but they all seem to fail.
Any suggestions?
the failing part is actually not the comparison of the symbols, but the check for listness.
user=> (list? (nth `(handler-case :type (println "test") (~'handle foo)) 3))
false
user=> (seq? (nth `(handler-case :type (println "test") (~'handle foo)) 3))
true
Sincerely
Meikel
This also means that macros should not use list? to test whether an
object is a nonatomic s-expression. Unfortunately core doesn't contain
a compact test for atomicity; to get all the list-y things that print
as (foo bar baz ...) you can use something like
(and
(coll? x)
(not (or (vector? x) (map? x) (set? x)))
which should return logical true only when x is list-y. Wrap that in a
predicate function and use it in your macros in place of list?.
And macroexpand (and pr in general) should have an option to mark what is a list and what is a cons thingy. That is confusing.
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
Combining coll? with (not (or (vector?) (map?) (set?))) eliminates the
other three types of coll and leaves seqs and lists.
Oddly, I seem to remember having had to work around a lack of seq?
previously, yet it says on the API page that it's been there since
1.0. Or perhaps it was the larger problem of determining if something
will work with (seq x) that was lacking built-in API...
It does indeed seem that seq? on lists returns true, so it looks like
you can just use that instead of list? in macros to check for (foo
...) s-expressions.