I am leaning macros in Clojure and have a question about macro expansion. In the repl, when I do this:
user=> (defmacro unless [pred a b] `(if (not ~pred) ~a ~b))
#'user/unless
user=> (macroexpand-1 '(unless (> 5 3) :foo :bar))
(if (clojure.core/not (> 5 3)) :foo :bar)
But when I do the same in a clj file:
(ns scratch-pad.core
(:gen-class))
(defmacro unless [pred a b]
`(if (not ~pred) ~a ~b))
(defn -main [& args]
(prn
(macroexpand-1 '(unless (> 5 3) :foo :bar))))
and run the code, I get this:
$ lein run
(unless (> 5 3) :foo :bar)
How do I get the code to print the same as the repl?
What's going on
This happens because of how the notion of the current namespace works in Clojure. macroexpand-1 expands its argument in the current namespace.
At the REPL, this will be user; you're defining the macro in the user namespace, then you call macroexpand-1 in that namespace and all is good.
In a :gen-class'd namespace, or indeed any other namespace, the compilation-time current namespace is that namespace itself. When you later call the code defined in this namespace, however, the then-current namespace will be whatever is appropriate at that point. That might be some other namespace as it gets compiled.
Finally, at your app's runtime, the default current namespace is user.
To see this, you could move the macro to a separate namespace also defining a function use-the-macro and calling this function at top level; the :gen-class'd namespace would then need to require or use the macro's namespace. Then lein run will print what you expect once (at the macro's namespace's compilation time) and the unexpanded form twice (when the macro's namespace is required by the main namespace and then when -main calls use-the-macro).
Solutions
The Clojure REPL controls the current namespace using binding; you can do the same:
(binding [*ns* (the-ns 'scratchpad.core)]
(prn (macroexpand-1 ...)))
You can also use syntax-quote instead of quote in -main:
(defn -main [& args]
(prn (macroexpand-1 `...)))
^- changed this
Of course if symbols other than unless were involved, you'd have to decide whether they should be namespace-qualified in the output and possibly prefix them with ~'. This is the point though -- syntax-quote is good for producing mostly "namespace-independent" code (which is what makes it so great for writing macros, besides the convenient syntax).
Another possible "fix" (tested on Clojure 1.5.1) is adding an in-ns call to -main:
(defn -main [& args]
(in-ns 'scratchpad.core)
(prn (macroexpand-1 '...)))
^- no change here this time
As with binding, this way you're actually getting the expansion of your original form in your original namespace.
Related
I would like a more detailed explanation of how macro expansion works, at least in Emacs Lisp but an overview of other Lisps would be appreciated. The way I usually see it explained is that the arguments of the macro are passed unevaluated to the body, which is then executed and returns a new LISP form. However, if I do
(defun check-one (arg)
(eq arg 1))
(defmacro check-foo (checker foo)
(if (checker 1)
`(,foo "yes")
`(,foo "no")))
I would expect
(check-foo check-one print)
to first expand to
(if (check-one 1)
`(print "yes")
`(print "no))
and then finally to
(print "yes")
but instead I get a "checker" function is void error. On the other hand, if I had defined
(defmacro check-foo (checker foo)
(if (funcall checker 1)
`(,foo "yes")
`(,foo "no")))
then I would have the expected behavior. So the expressions do get replaced in the body unevaluated, but for some reason functions do not work? What is the step-by-step procedure the interpreter follows when macroexpanding? Is there a good text-book that explains this rigorously?
Macros are functions ...
A good way to think about macros is that they are simply functions, like any other function.
... which operate on source code
But they are functions whose arguments are source code, and whose value is also source code.
Looking at macro functions
Macros being functions is not quite explicit in elisp: some of the lower-level functionality is, I think, not exposed. But in Common Lisp this is quite literally how macros are implemented: a macro has an associated function, and this function gets called to expand the macro, with its value being the new source code. For instance, if you are so minded you could write macros in Common Lisp like this.
(defun expand-fn (form environment)
;; not talking about environment
(declare (ignore environment))
(let ((name (second form))
(arglist (third form))
(body (cdddr form)))
`(function (lambda ,arglist
(block ,name
,#body)))))
(setf (macro-function 'fn) #'expand-fn)
And now fn is a macro which will construct a function which 'knows its name', so you could write
(fn foo (x) ... (return-from foo x) ...)
which turns into
(function (lambda (x) (block foo ... (return-from foo x))))
In Common Lisp, defmacro is then itself a macro which arranges for a suitable macro function to be installed and also deals with making the macro available at compile time &c.
In elisp, it looks as if this lower layer is not specified by the language, but I think it's safe to assume that things work the same way.
So then the job of a macro is to take a bunch of source code and compute from it another bunch of source code which is the expansion of the macro. And of course the really neat trick is that, because source code (both arguments and values) is represented as s-expressions, Lisp is a superb language for manipulating s-expressions, you can write macros in Lisp itself.
Macroexpansion
There are a fair number of fiddly corner cases here such as local macros and so on. But here is, pretty much, how this works.
Start with some form <f>:
If <f> is (<a> ...) where <a> is a symbol, check for a macro function for <a>. If it has one, call it on the whole form, and call the value it returns <f'>: now simply recurse on <f'>.
If <f> is (<a> ...) where <a> is a symbol which names a special operator (something like if) then recurse on the subforms of the special operator which its rules say must be macroexpanded. As an example, in a form like (if <x> <y> <z>) all of <x>, <y>, & <z> need to be macroexpanded, while in (setq <a> <b>), only <b> would be subject to macroexpansion, and so on: these rules are hard-wired, which is why special operators are special.
If <f> is (<a> ...) where <a> is a symbol which is neither of the above cases, then it's a function call, and the forms in the body of the form are macroexpanded, and that's it.
If <f> is ((lambda (...) ...) ...) then the forms in the body of the lambda (but not its arguments!) are macroexpanded and then the case is the same as the last one.
Finally <f> might not be a compound form: nothing to do here.
I think that's all the cases. This is not a complete description of the process because there are complications like local macros and so on. But it's enough I think.
Order of macroexpansion
Note that macroexpansion happens 'outside in': a form like (a ...) is expanded until you get something which isn't a macro form, and only then is the body, perhaps, expanded. That's because, until the macro is completely expanded, you have no idea which, if any, of the subforms are even eligible for macroexpansion.
Your code
My guess is that what you want to happen is that (check-foo bog foo) should turn into (if (bog 1) (foo yes) (foo no)). So the way to get this is that this form is what the macro function needs to return. We could write this using the CL low-level facilities:
(defun check-foo-expander (form environment)
;; form is like (check-foo pred-name function-name)
(declare (ignore environment)) ;still not talking about environment
`(if (,(second form) 1)
(,(third form) "yes")
(,(third form) "no")))
And we can check:
> (check-foo-expander '(check-foo bog foo) nil)
(if (bog 1) (foo "yes") (foo "no"))
And then install it as a macro:
> (setf (macro-function 'check-foo) #'check-foo-expander)
And now
> (check-foo evenp print)
"no"
"no"
> (check-foo oddp print)
"yes"
"yes"
But it's easier to write it using defmacro:
(defmacro check-foo (predicate function)
`(if (,predicate 1)
(,function "yes")
(,function "no")))
This is the same thing (more-or-less), but easier to read.
I would like to get the name of the file where a particular function or macro definition was last written, for various documentation & testing purposes?
I have posted an answer that works well from me, after the help of PJB on #CommonLisp (IRC.LIBERA.CHAT), but will accept any answers which provide a portable solution that does not depend on SWANK or provides additional detail on how to achieve the same in other IDEs like LispWorks, ACL, etc.
If what you seek is a portable solution – one that is written in portable CL – then the answer to that is to define wrappers for defining forms and then use the wrappers.
(defvar *flocs* (make-hash-table :test #'equal))
(defgeneric function-location (f/name)
(:method ((name t))
(values (gethash name *flocs* nil) t))
(:method ((f function))
(multiple-value-bind (le cp nm) (function-lambda-expression f)
(declare (ignore le cp))
(if nm
(function-location nm)
(values nil nil)))))
(defmacro define-function (f args &body doc/decls/forms)
(when (or *load-pathname* *compile-file-pathname*)
;; Prefer *load-pathname*
(setf (gethash f *flocs*) (or *load-pathname* *compile-file-pathname*)))
`(defun ,f ,args ,#doc/decls/forms))
In real life you'd call define-function defun of course, and similarly with define-variable etc, and then construct a conduit package for CL which exported all the CL symbols while replacing the defining forms with these ones.
If what you seek is a portable solution in the sense that it exports some standard interface but has varying implementation-dependent backends, then probably looking at what SLY or SWANK do is a good start. In the case of LW you would want the backend to use DSPECs which are how it deals with location information:
> (dspec:dspec-definition-locations '(defun foo))
(((defun foo) :listener))
> (dspec:dspec-definition-locations '(defun needs))
(((defmacro needs)
#P"..."))
> (defclass foo () ())
#<standard-class foo 402000B763>
> (dspec:name-definition-locations dspec:*dspec-classes* 'foo)
(((defclass foo) :listener) ((defun foo) :listener))
PJB on #CommonLisp (IRC.LIBERA.CHAT) greatly assisted and provided the below answer (which I have paraphrased so any mistakes are on my end):
Firstly, CL is a lisp-2 (actually, lisp-∞) and thus there may not be a single definition attached to a symbol. For example, which foo is being referred to in the below?
(deftype foo () (member foo))
(defvar foo 'foo)
(defun foo () foo)
In addition, as an example, symbols may be defined in the REPL (no associated filename), so this is not a straightforward question that can be answered without making assumptions on the intent.
Now, when the behaviour of M-. is satisfactory for your requirements, you could look in slime/swank what the implementation specific API is to do it.
This should point you to swank:find-definition-for-emacs, which may be what you are after:
(swank:find-definitions-for-emacs "foo") #| -->
(("#'foo"
(:location (:file "/private/tmp/foo.lisp")
(:position 50)
(:snippet "(defun foo () foo)")))
("(type foo)"
(:location (:file "/private/tmp/foo.lisp")
(:position 1)
(:snippet "(deftype foo () '(member foo))")))
("(variable foo)"
(:location (:file "/private/tmp/foo.lisp")
(:position 32)
(:snippet "(defvar foo 'foo)"))))
Make sure to load swank as a dependency in your .asd files if you want to rely on the above.
EDIT: I also found the below very useful (and swank has a similar file for most implementations, so just go through each to see their equivalents):
https://github.com/slime/slime/blob/68c58c0194ff03cd147fcec99f0ee90ba9178875/swank/sbcl.lisp#L811
The function call (sb-introspect:find-definition-sources-by-name name type) (name is a symbol, type is a keyword, e.g. :function - refer above link) returns the file in which a definition is stored, assuming you are using SBCL. More (SBCL) details also in:
https://github.com/sbcl/sbcl/blob/master/contrib/sb-introspect/introspect.lisp
I have sample code like this:
#!/usr/bin/guile -s
!#
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body)))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)
it run but I've got error from compiler
ERROR: Unbound variable: process
functions inside macros should be allowed, why I got this error?
Functions inside macros are allowed in Guile and in most other Scheme dialects.
However, the crucial question is: Which functions are available for a macro to call out during the expansion process?
Think of it this way: When the compiler is processing your code, it is first focused on turning your source code into something that can be run at some point in the future. But the compiler might not necessarily be able to execute those same functions right now while it is compiling them, at the same time that your macro is running and expanding the source code in general.
Why wouldn't such a function be available? Well, one example would be: What if the function's body used the macro you are in the midst of defining? Then you would have a little chicken/egg problem. The function would need to run the macro to be compiled (since the macro use in the body needs to be expanded, at compile-time) ... But the macro would need the compiled function available in order to even run!
(Furthermore, there might be some functions that you only want to be available at compile-time, as a helper for your macros, but that you do not want to be available at run-time, so that it will not be included in your program executable when you deploy it, as that would waste space in the deployed binary.)
One of my favorite papers describing this problem, and the particular solution adopted by MzScheme (now known as Racket), is the "You Want It When" paper by Matthew Flatt.
So, this is a problem that any Scheme dialect with a procedural macro system has to deal with in some way, and Guile is no exception.
In Guile's case, one fix that is directly documented in the Guile manual is to use the eval-when special form, which allows you to specify at what phases a particular definition is meant to be available.
(The "You Want It When" paper referenced above describes some problems with eval-when, but since it is what the Guile manual documents, I'm going to stick with it for now. I do recommend that after you understand eval-when, that you then look into Racket's solution, and see if Guile offers anything similar.)
So in your case, since you want the process function to be available at compile-time (for use in the macro definition), you could write:
#!/usr/bin/guile -s
!#
(eval-when (expand)
(define (process body)
(list 'list (map (lambda (lst)
(list 'quote (car lst)))
body))))
(defmacro macro (body)
(list 'quote (process body)))
(display (macro ((foo bar) (bar baz))))
(newline)
Given this situation:
(defmacro mac1 ...)
(defun func1 ()
(mac1 ...))
Redefinition of mac1 in the live environment will not affect func1 until it is itself recompiled.
Is there a way to get emacs or lisp to automatically recompile func1 whenever mac1 is recompiled?
Something like this in the source would be acceptable:
(watch
(defmacro mac1 ...))
(on-signal (mac1)
(defun func1 ...))
Not that hard to implement, but I would rather avoid wheel reinvention.
Macros are not necessarily compiled. If you are using SBCL (see manual), there is a variable named sb-ext:*evaluator-mode* which can be set to :interpret so that macro are expanded during evaluation. Other implementations might provide something similar. That allows you to change the definitions of macros without recompiling call sites like you already do with functions.
Alternatively, slime defines a function named slime-who-macroexpands. You'd have to dig a little bit to see how it works and maybe exploit it, either in the Common Lisp environment (swank) or the emacs side.
For example in LispWorks you can do the following. Probably SBCL has a similar facility.
Let's say we have this:
(defmacro foo ()
`(list 1 2 3))
(defun bar () (first (foo)))
(defun baz () (second (foo)))
Now you can ask who calls foo:
CL-USER 11 > (who-calls 'foo)
(BAZ BAR)
This makes it easy to re-compile both functions:
CL-USER 12 > (mapcar 'compile (who-calls 'foo))
;;;*** Warning in BAZ: The definition of BAZ is already compiled.
;;;*** Warning in BAR: The definition of BAR is already compiled.
(BAZ BAR)
Since LispWorks keeps a who-calls database, one can recompile all functions which directly use and depend on other functions/macros.
The editor has the command Edit Callers and Continue Tags Search to find the callers and then to recompile them manually. It should be easy/possible to write an editor command which recompiles all callers.
I am trying to implement a huge Java interface with numerous (~50) getter and setter methods (some with irregular names). I thought it would be nice to use a macro to reduce the amount of code. So instead of
(def data (atom {:x nil}))
(reify HugeInterface
(getX [this] (:x #data))
(setX [this v] (swap! data assoc :x v)))
I want to be able to write
(def data (atom {:x nil}))
(reify HugeInterface
(set-and-get getX setX :x))
Is this set-and-get macro (or something similar) possible? I haven't been able to make it work.
(Updated with a second approach -- see below the second horizontal rule -- as well as some explanatory remarks re: the first one.)
I wonder if this might be a step in the right direction:
(defmacro reify-from-maps [iface implicits-map emit-map & ms]
`(reify ~iface
~#(apply concat
(for [[mname & args :as m] ms]
(if-let [emit ((keyword mname) emit-map)]
(apply emit implicits-map args)
[m])))))
(def emit-atom-g&ss
{:set-and-get (fn [implicits-map gname sname k]
[`(~gname [~'this] (~k #~(:atom-name implicits-map)))
`(~sname [~'this ~'v]
(swap! ~(:atom-name implicits-map) assoc ~k ~'v))])})
(defmacro atom-bean [iface a & ms]
`(reify-from-maps ~iface {:atom-name ~a} ~emit-atom-g&ss ~#ms))
NB. that the atom-bean macro passes the actual compile-time value of emit-atom-g&ss on to reify-from-maps. Once a particular atom-bean form is compiled, any subsequent changes to emit-atom-g&ss have no effect on the behaviour of the created object.
An example macroexpansion from the REPL (with some line breaks and indentation added for clarity):
user> (-> '(atom-bean HugeInterface data
(set-and-get setX getX :x))
macroexpand-1
macroexpand-1)
(clojure.core/reify HugeInterface
(setX [this] (:x (clojure.core/deref data)))
(getX [this v] (clojure.core/swap! data clojure.core/assoc :x v)))
Two macroexpand-1s are necessary, because atom-bean is a macro which expands to a further macro call. macroexpand would not be particularly useful, as it would expand this all the way to a call to reify*, the implementation detail behind reify.
The idea here is that you can supply an emit-map like emit-atom-g&ss above, keyed by keywords whose names (in symbolic form) will trigger magic method generation in reify-from-maps calls. The magic is performed by the functions stored as functions in the given emit-map; the arguments to the functions are a map of "implicits" (basically any and all information which should be accessible to all method definitions in a reify-from-maps form, like the name of the atom in this particular case) followed by whichever arguments were given to the "magic method specifier" in the reify-from-maps form. As mentioned above, reify-from-maps needs to see an actual keyword -> function map, not its symbolic name; so, it's only really usable with literal maps, inside other macros or with help of eval.
Normal method definitions can still be included and will be treated as in a regular reify form, provided keys matching their names do not occur in the emit-map. The emit functions must return seqables (e.g. vectors) of method definitions in the format expected by reify: in this way, the case with multiple method definitions returned for one "magic method specifier" is relatively simple. If the iface argument were replaced with ifaces and ~iface with ~#ifaces in reify-from-maps' body, multiple interfaces could be specified for implementation.
Here's another approach, possibly easier to reason about:
(defn compile-atom-bean-converter [ifaces get-set-map]
(eval
(let [asym (gensym)]
`(fn [~asym]
(reify ~#ifaces
~#(apply concat
(for [[k [g s]] get-set-map]
[`(~g [~'this] (~k #~asym))
`(~s [~'this ~'v]
(swap! ~asym assoc ~k ~'v))])))))))
This calls on the compiler at runtime, which is somewhat expensive, but only needs to be done once per set of interfaces to be implemented. The result is a function which takes an atom as an argument and reifies a wrapper around the atom implementing the given interfaces with getters and setters as specified in the get-set-map argument. (Written this way, this is less flexible than the previous approach, but most of the code above could be reused here.)
Here's a sample interface and a getter/setter map:
(definterface IFunky
(getFoo [])
(^void setFoo [v])
(getFunkyBar [])
(^void setWeirdBar [v]))
(def gsm
'{:foo [getFoo setFoo]
:bar [getFunkyBar setWeirdBar]})
And some REPL interactions:
user> (def data {:foo 1 :bar 2})
#'user/data
user> (def atom-bean-converter (compile-atom-bean-converter '[IFunky] gsm))
#'user/atom-bean-converter
user> (def atom-bean (atom-bean-converter data))
#'user/atom-bean
user> (.setFoo data-bean 3)
nil
user> (.getFoo atom-bean)
3
user> (.getFunkyBar data-bean)
2
user> (.setWeirdBar data-bean 5)
nil
user> (.getFunkyBar data-bean)
5
The point is reify being a macro itself which is expanded before your own set-and-get macro - so the set-and-get approach doesn't work. So, instead of an inner macro inside reify, you need a macro on the "outside" that generates the reify, too.
Since the trick is to expand the body before reify sees it, a more general solution could be something along these lines:
(defmacro reify+ [& body]
`(reify ~#(map macroexpand-1 body)))
You can also try to force your macro to expand first:
(ns qqq (:use clojure.walk))
(defmacro expand-first [the-set & code] `(do ~#(prewalk #(if (and (list? %) (contains? the-set (first %))) (macroexpand-all %) %) code)))
(defmacro setter [setterf kw] `(~setterf [~'this ~'v] (swap! ~'data assoc ~kw ~'v)))
(defmacro getter [getterf kw] `(~getterf [~'this] (~kw #~'data)))
(expand-first #{setter getter}
(reify HugeInterface
(getter getX :x)
(setter setX :x)))