On May 1, 4:42 pm, André Thieme <splendidl...@googlemail.com> wrote:
> I am currently writing a neat logging lib and want it to support dynamic
> and static logging. When I activate (static-logging!) then the log macro
> (log :warn "message") will check during macro expansion time which log
> level is currently set and decides based on that if code will be
> generated that logs the message or not.
>
> The user can set any log function and for that purpose I offer some
> closure factories, such as make-writer-logger or make-file-logger.
> Two useful writer-loggers are defined as:
> (def out-logger (make-writer-logger *out*))
> (def err-logger (make-writer-logger *err*))
>
> The make-writer-logger returns a closure that takes a level and a
> message and writes this to the given Writer. Now my current logger is
> stored in an atom, for example the default is
> (let [logger (atom out-logger)] …)
> Inside my log macro I want to call @logger, which unfortunately results
> in an Exception:
> “No matching ctor found for class my.logger$make_writer_logger$fn__1588”
>
> Please try this minimal example in your REPL:
> (defn f [x] (fn [] x)) ; the closure factory
> (def foo (f 0)) ; a useful instance
> (defmacro bar [] `(let [a# ~foo]))
> and then call (bar)
>
> As soon f doesn’t return a closure but just a fn, then this Exception
> is not thrown, but instead the code works.
>
> Just from looking at the macro definition I would say it should work for
> any object as long foo is defined.
>
> Is that behaviour a bug? How easy is it to fix it?
> Are there any work-arounds?

You can't embed a function in code as a raw function object - you need
to return code that will result in that function. That it happens to
work for non-closure functions is, as I understand it, a happy (or
not?) accident.

The "workaround" is simple enough: don't do it. Instead, return code
that will be evaluated in the expansion context and have the effect
you want.

user> (defmacro bar [[name] & body] `(let [~name (f 0)] ~@body))
#'user/bar
user> (bar [log] (log))
0

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to