Show generated code from lisp macro - macros

I am very new to lisp and this may well be a very stupid/obvious question but in common lisp can you show the generated code from a macro ?
So for the example
(defmacro nil! (var)
(list 'setq var nil))
I'd like to be able see the expanded code
(setq a nil)

As Diego said... MACROEXPAND-1.
* (macroexpand-1 '(nil! frob))
(SETQ FROB NIL)
T
*

Related

How to re-write this Common Lisp macro avoiding the back-quote notation?

I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.
In the last chapter, on Macros, the author presents examples to re-write the built-in incf macro. He teaches the concept with two different approaches: using back-quote notation and without it. Such as:
(defmacro list-notation-my-incf (x)
(list 'setq x (list '+ x 1)))
(defmacro backquote-notation-my-incf (x)
`(setq ,x (+ ,x 1)))
Later, the author introduces another example:
In the example below, TWO-FROM-ONE is a macro that takes a function
name and another object as arguments; it expands into a call to the
function with two arguments, both of which are the quoted object.
He only uses back-quote character to do it:
(defmacro two-from-one (func object)
`(,func ',object ',object))
And it works as expected:
CL-USER> (two-from-one cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)
Using slime-macroexpad-1, I have:
(CONS 'STACK-OVERFLOW 'STACK-OVERFLOW)
As an exercise that I created for myself, I tried doing the same, but avoiding the back-quote notation. Unfortunately, I could not make it work:
(defmacro list-two-from-one (func object)
(list func (quote object) (quote object)))
Slime throws the error:
The variable OBJECT is unbound.
[Condition of type UNBOUND-VARIABLE]
Doing a macro expansion, I see:
(CONS OBJECT OBJECT)
If I try a different approach, it seems to be closer, but it does not work either:
(defmacro list-two-from-one (func object)
(list func object object))
Throws the error:
The variable STACK-OVERFLOW is unbound.
[Condition of type UNBOUND-VARIABLE]
And, finally, the macro expansion indicates:
(CONS STACK-OVERFLOW STACK-OVERFLOW)
I feel stuck. How do I successfully re-write the macro without using back-quote notation?
Thanks.
What you are looking for is something like
(defmacro list-two-from-one (func object)
(list func (list 'quote object) (list 'quote object)))
basically, the body of a macro should return the code, that, when evaluated, produces the desired result.
I.e., the macro body should produce (CONS 'STACK-OVERFLOW 'STACK-OVERFLOW).
Since 'a is the same as (quote a), you want your macro to produce
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))
which is what my defmacro above returns.
Your macro should expand to:
CL-USER 10 > (macroexpand '(two-from-one2 cons stack-overflow))
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))
So create lists with quote like this:
(defmacro two-from-one2 (func object)
(list func (list 'quote object) (list 'quote object)))
Test:
CL-USER 9 > (two-from-one2 cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)

Substitute symbol name in macro

How can I substitute a symbol name into a function created in a macro? I think I am missing something obvious here. For example, I am trying to make a macro that defines some variables and functions similar to the following,
(cl-defmacro mac (pkg)
(let (
;; Define some variables
(sym (intern (concat pkg "-file")))
(sym-def "default-file.el")
(sym-doc (concat "A custom var from `" pkg "'."))
;; Define some functions
(symfn (intern (concat pkg "-fn")))
(symfn-doc (concat "A function for `" pkg "'.")))
`(list
(defcustom ,sym ,sym-def ,sym-doc
:group (quote ,(make-symbol pkg))
:type '(choice (const :tag "None" nil)
file))
(defun ,symfn ()
,symfn-doc
(interactive)
(fn ,sym)))))
The function returned makes a call out to another function (fn) with a signature like
(defun fn (var) (symbol-value var))
So, it is expecting a call like (fn 'some-var). And, I want to be able to use the macro like
(mac "pack")
And have the following work,
pack-file ; works: "default-file.el"
(pack-fn) ; error: not a symbol
I have tried things like (quote ,sym), symbol-name, and others... But can't seem to get it right.
You want the call to fn to be (fn ',sym) (which you mention you tried in the question, but I suspect got wrong somehow).
You probably also want the expansion of the macro to be (progn ...) instead of (list ...).
(This was originally a comment: I'm putting it here just so there's an answer.)

Can't call functions defined in macro with names generated by make-symbol

I'm trying to write an ELisp macro to generate a multiple functions based on some common data. For example, when I want to compute the fn names I write something like (I'm ignoring hygiene for the moment, I'm passing a symbol literal into the macro so evaluation shouldn't matter):
(cl-defmacro def-fns (sym)
"SYM."
(let ((s1 (make-symbol (concat (symbol-name sym) "-1")))
(s2 (make-symbol (concat (symbol-name sym) "-2"))))
`(progn (defun ,s1 () (+ 1 2 3))
(defun ,s2 () "six"))))
which I expect to generate 2 fns when invoked, called foo-1 and foo-2.
I should then be able to invoke the macro and fns like so:
(def-fns foo)
(foo-1)
;; => 6
(foo-2)
;; -> "six
Even the macroexpansion of (def-fns foo) in Emacs suggests that this should be the case:
(progn
(defun foo-1 nil (+ 1 2 3))
(defun foo-2 nil "six"))
However, when I evaluate the def-fns definition and invoke it it does not generate those functions. Why is this the case? This technique works in Common Lisp and in Clojure (which have very similar macro systems), so why not in ELisp?
Your code would not work in CL either.
The problem is with make-symbol - it creates a new symbol, so that
(eq (make-symbol "A") (make-symbol "A"))
==> nil
This means that your macro creates the functions but binds them to symbols which you no longer have a handle on.
When you evaluate (foo-1), Emacs Lisp reader tries to find the function binding of the interned symbol foo-1, not the fresh uninterned symbol your macro created.
You need to use intern instead: it makes the symbol "generally available", so to speak:
(eq (intern "a") (intern "a))
==> t
So, the corrected code looks like this:
(defmacro def-fns (sym)
"SYM."
(let ((s1 (intern (concat (symbol-name sym) "-1")))
(s2 (intern (concat (symbol-name sym) "-2"))))
`(progn (defun ,s1 () (+ 1 2 3))
(defun ,s2 () "six"))))
(def-fns foo)
(foo-1)
==> 6
(foo-2)
==> "six"
Notes:
If you were using CL, the uninterned symbols would have been printed as #:foo-1 and the source of your problem would have been obvious to you.
It is exceedingly rare that you really need to use make-symbol. Usually, you want to use either intern or gensym.

In LISP, what's the difference between "let" and "with"?

A simple example to show the differences in action would really help, since to me they both just seem interchangeable? Thanks :)
In Common Lisp, at least, you can only use with in the context of a loop macro. See the Common Lisp Hyperspec.
They are indeed functionally equivalent.
In fact, at least SBCL expands any use of with in a loop macro invocation into an enclosing LET form.
Running the following:
(macroexpand '(loop with foo = 5 repeat 10 collect foo))
Results in the following expansion:
(BLOCK NIL
(LET ((FOO 5))
(LET ((#:LOOP-REPEAT-1681 (CEILING 10)))
(DECLARE (TYPE INTEGER #:LOOP-REPEAT-1681))
(SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1682
#:LOOP-LIST-TAIL-1683)
(SB-LOOP::LOOP-BODY NIL
((IF (<= #:LOOP-REPEAT-1681 0)
(GO SB-LOOP::END-LOOP)
(DECF #:LOOP-REPEAT-1681)))
((SB-LOOP::LOOP-COLLECT-RPLACD
(#:LOOP-LIST-HEAD-1682 #:LOOP-LIST-TAIL-1683)
(LIST FOO)))
((IF (<= #:LOOP-REPEAT-1681 0)
(GO SB-LOOP::END-LOOP)
(DECF #:LOOP-REPEAT-1681)))
((RETURN-FROM NIL
(SB-LOOP::LOOP-COLLECT-ANSWER
#:LOOP-LIST-HEAD-1682))))))))

How do I do closures in Emacs Lisp?

I'm trying to create a function on the fly that would return one constant value.
In JavaScript and other modern imperative languages I would use closures:
function id(a) {
return function() {return a;};
}
but Emacs lisp doesn't support those.
I can create mix of identity function and partial function application but it's not supported either.
So how do I do that?
Found another solution with lexical-let
(defun foo (n)
(lexical-let ((n n)) #'(lambda() n)))
(funcall (foo 10)) ;; => 10
Real (Not Fake) Closures in Emacs 24.
Although Emacs 24 has lexical scooping when the variable lexical-binding has value t, the defun special form doesn’t work properly in lexically bound contexts (at least not in Emacs 24.2.1.) This makes it difficult, but not impossible, to define real (not fake) closures. For example:
(let ((counter 0))
(defun counting ()
(setq counter (1+ counter))))
will not work as expected because the symbol counter in the defun will be bound to the global variable of that name, if there is one, and not the lexical variable define in the let. When the function counting is called, if the global variable doesn’t, exist then it will obviously fail. Hoever if there is such a global variable it be updated, which is probably not what was intended and could be a hard to trace bug since the function might appear to be working properly.
The byte compiler does give a warning if you use defun in this way and presumably the issue will be addressed in some future version of Emacs, but until then the following macro can be used:
(defmacro defun** (name args &rest body)
"Define NAME as a function in a lexically bound context.
Like normal `defun', except that it works correctly in lexically
bound contexts.
\(fn NAME ARGLIST [DOCSTRING] BODY...)"
(let ((bound-as-var (boundp `,name)))
(when (fboundp `,name)
(message "Redefining function/macro: %s" `,name))
(append
`(progn
(defvar ,name nil)
(fset (quote ,name) (lambda (,#args) ,#body)))
(if bound-as-var
'nil
`((makunbound `,name))))))
If you define counting as follows:
(let ((counter 0))
(defun** counting ()
(setq counter (1+ counter))))
it will work as expected and update the lexically bound variable count every time it is invoked, while returning the new value.
CAVEAT: The macro will not work properly if you try to defun** a function with the same name as one of the lexically bound variables. I.e if you do something like:
(let ((dont-do-this 10))
(defun** dont-do-this ()
.........
.........))
I can’t imagine anyone actually doing that but it was worth a mention.
Note: I have named the macro defun** so that it doesn’t clash with the macro defun* in the cl package, however it doesn’t depend in any way on that package.
Stupid idea: how about:
(defun foo (x)
`(lambda () ,x))
(funcall (foo 10)) ;; => 10
Emacs lisp only has dynamic scoping. There's a lexical-let macro that approximates lexical scoping through a rather terrible hack.
Emacs 24 has lexical binding.
http://www.emacswiki.org/emacs/LexicalBinding
;; -*- lexical-binding:t -*-
(defun create-counter ()
(let ((c 0))
(lambda ()
(setq c (+ c 1))
c)))
(setq counter (create-counter))
(funcall counter) ; => 1
(funcall counter) ; => 2
(funcall counter) ; => 3 ...
http://www.emacswiki.org/emacs/FakeClosures