Usually it's better to create a sentinel (Object.) to lock on to avoid sharing
it. (Well really it's best to avoid locking at all and use Clojure state
constructs if you can.)
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group,
user=> (def obj (Object.))
#'user/obj
user=> (defmacro mac1 [& body] `(locking ~obj ~@body))
#'user/mac1
user=> (mac1 nil)
CompilerException java.lang.RuntimeException: Can't embed object in code,
maybe print-dup not defined: java.lang.Object@2a747a37,
compiling:(NO_SOURCE_PATH:1:1)
Why am I
I think the reason is in macroexpand-1 result:
user=> (macroexpand-1 '(mac1 1))
(clojure.core/locking # 1)
It's not a valid form to be read and eval by clojure reader,the object form
can't be parsed.
If define obj to be a map {}, it works fine:
user=> (def obj {})
#'user/obj
user=> (mac1 1)
1
The problem here is that you are splicing in obj when there is no need to.
You actually want your generated code to refer to obj. So just
(defmacro mac1 [& body] `(locking obj ~@body))
is fine.
dennis' solution will work too, but it will work almost accidentally? All
blank maps evaluate to the