Eliminate eval in macro using correct combination of commas and backquotes - macros

I've written a macro that works as intended. The problem is that it contains an eval. I'd like to get rid of it but try as I might, I can't find the correct combination of backquotes and commas to do so.
(defmacro mymacro (x &body body)
`(myothermacro ,(fun1 (eval x))
,#body))
Here myothermacro is a macro and fun1 is a function.
Here is the desired behaviour:
(defvar v 88)
(defun fun1 (z) (1+ z))
(defmacro mymacro (x &body body)
`(myothermacro ,(fun1 (eval x))
,#body))
(macroexpand-1 '(mymacro v 42 43 44))
=> (MYOTHERMACRO 89 42 43 44)

There is no amount of backquotes that can help you here. In a scenario you have more than one backquote there are equally as many quasiquote and thus you can get different layers of quoted data but not data evaluated more than once.
It's important to understand that a macro does not do anything runtime. Thus if you are to use a macro eg (mymacro variable (my-function x)) the macro function mymacro is fed variable and (my-function x) right away and the result in put in place. variable might not exist yet so evaluating it would be premature. When you define a function that uses the macro it will most likely expand the macros before storing the function. When in runtime there are no macros because they are all expanded, but this is the very first time it's possible to make conclusions if the arguments passed to the macro and its expansion actually makes sense according to the lexical environment and global bindings.
Perhaps if you added more information would there be a way to help you solve your actual problem since I get a feeling this is a XY problem.

You need to use use read-time evaluation if I got your idea right.
Something like this:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defparameter *foo* "foo"))
(defmacro bar (arg)
`(list #.*foo* ,arg))
CL-USER> (macroexpand '(bar "bar"))
(LIST "foo" "bar")
You may be better with defconstant instead of defparameter because it's clearer about intentions.

Related

Lisp changes function to lambda expression when stored in function cell

In this post, I ask tangentially why when I declare in SBCL
(defun a (&rest x)
x)
and then check what the function cell holds
(describe 'a)
COMMON-LISP-USER::A
[symbol]
A names a compiled function:
Lambda-list: (&REST X)
Derived type: (FUNCTION * (VALUES LIST &OPTIONAL))
Source form:
(LAMBDA (&REST X) (BLOCK A X))
I see this particular breakdown of the original function. Could someone explain what this output means? I'm especially confused by the last line
Source form:
(LAMBDA (&REST X) (BLOCK A X))
This is mysterious because for some reason not clear to me Lisp has transformed the original function into a lambda expression. It would also be nice to know the details of how a function broken down like this is then called. This example is SBCL. In Elisp
(symbol-function 'a)
gives
(lambda (&rest x) x)
again, bizarre. As I said in the other post, this is easier to understand in Scheme -- but that created confusion in the answers. So once more I ask, Why has Lisp taken a normal function declaration and seemingly stored it as a lambda expression?
I'm still a bit unclear what you are confused about, but here is an attempt to explain it. I will stick to CL (and mostly to ANSI CL), because elisp has a lot of historical oddities which just make things hard to understand (there is an appendix on elisp). Pre-ANSI CL was also a lot less clear on various things.
I'll try to explain things by writing a macro which is a simple version of defun: I'll call this defun/simple, and an example of its use will be
(defun/simple foo (x)
(+ x x))
So what I need to do is to work out what the expansion of this macro should be, so that it does something broadly equivalent (but simpler than) defun.
The function namespace & fdefinition
First of all I assume you are comfortable with the idea that, in CL (and elisp) the namespace of functions is different than the namespace of variable bindings: both languages are lisp-2s. So in a form like (f x), f is looked up in the namespace of function bindings, while x is looked up in the namespace of variable bindings. This means that forms like
(let ((sin 0.0))
(sin sin))
are fine in CL or elisp, while in Scheme they would be an error, as 0.0 is not a function, because Scheme is a lisp-1.
So we need some way of accessing that namespace, and in CL the most general way of doing that is fdefinition: (fdefinition <function name>) gets the function definition of <function name>, where <function name> is something which names a function, which for our purposes will be a symbol.
fdefinition is what CL calls an accessor: this means that the setf macro knows what to do with it, so that we can mutate the function binding of a symbol by (setf (fdefinition ...) ...). (This is not true: what we can access and mutate with fdefinition is the top-level function binding of a symbol, we can't access or mutate lexical function bindings, and CL provides no way to do this, but this does not matter here.)
So this tells us what our macro expansion needs to look like: we want to set the (top-level) definition of the name to some function object. The expansion of the macro should be like this:
(defun/simple foo (x)
x)
should expand to something involving
(setf (fdefinition 'foo) <form which makes a function>)
So we can write this bit of the macro now:
(defmacro defun/simple (name arglist &body forms)
`(progn
(setf (fdefinition ',name)
,(make-function-form name arglist forms))
',name))
This is the complete definition of this macro. It uses progn in its expansion so that the result of expanding it is the name of the function being defined, which is the same as defun: the expansion does all its real work by side-effect.
But defun/simple relies on a helper function, called make-function-form, which I haven't defined yet, so you can't actually use it yet.
Function forms
So now we need to write make-function-form. This function is called at macroexpansion time: it's job is not to make a function: it's to return a bit of source code which will make a function, which I'm calling a 'function form'.
So, what do function forms look like in CL? Well, there's really only one such form in portable CL (this might be wrong, but I think it is true), which is a form constructed using the special operator function. So we're going to need to return some form which looks like (function ...). Well, what can ... be? There are two cases for function.
(function <name>) denotes the function named by <name> in the current lexical environment. So (function car) is the function we call when we say (car x).
(function (lambda ...)) denotes a function specified by (lambda ...): a lambda expression.
The second of these is the only (caveats as above) way we can construct a form which denotes a new function. So make-function-form is going to need to return this second variety of function form.
So we can write an initial version of make-function-form:
(defun make-function-form (name arglist forms)
(declare (ignore name))
`(function (lambda ,arglist ,#forms)))
And this is enough for defun/simple to work:
> (defun/simple plus/2 (a b)
(+ a b))
plus/2
> (plus/2 1 2)
3
But it's not quite right yet: one of the things that functions defined by defun can do is return from themselves: they know their own name and can use return-from to return from it:
> (defun silly (x)
(return-from silly 3)
(explode-the-world x))
silly
> (silly 'yes)
3
defun/simple can't do this, yet. To do this, make-function-form needs to insert a suitable block around the body of the function:
(defun make-function-form (name arglist forms)
`(function (lambda ,arglist
(block ,name
,#forms))))
And now:
> (defun/simple silly (x)
(return-from silly 3)
(explode-the-world x))
silly
> (silly 'yes)
3
And all is well.
This is the final definition of defun/simple and its auxiliary function.
Looking at the expansion of defun/simple
We can do this with macroexpand in the usual way:
> (macroexpand '(defun/simple foo (x) x))
(progn
(setf (fdefinition 'foo)
#'(lambda (x)
(block foo
x)))
'foo)
t
The only thing that's confusing here is that, because (function ...) is common in source code, there's syntactic sugar for it which is #'...: this is the same reason that quote has special syntax.
It's worth looking at the macroexpansion of real defun forms: they usually have a bunch of implementation-specific stuff in them, but you can find the same thing there. Here's an example from LW:
> (macroexpand '(defun foo (x) x))
(compiler-let ((dspec::*location* '(:inside (defun foo) :listener)))
(compiler::top-level-form-name (defun foo)
(dspec:install-defun 'foo
(dspec:location)
#'(lambda (x)
(declare (system::source-level
#<eq Hash Table{0} 42101FCD5B>))
(declare (lambda-name foo))
x))))
t
Well, there's a lot of extra stuff in here, and LW obviously has some trick around this (declare (lambda-name ...)) form which lets return-from work without an explicit block. But you can see that basically the same thing is going on.
Conclusion: how you make functions
In conclusion: a macro like defun, or any other function-defining form, needs to expand to a form which, when evaluated, will construct a function. CL offers exactly one such form: (function (lambda ...)): that's how you make functions in CL. So something like defun necessarily has to expand to something like this. (To be precise: any portable version of defun: implementations are somewhat free to do implementation-magic & may do so. However they are not free to add a new special operator.)
What you are seeing when you call describe is that, after SBCL has compiled your function, it's remembered what the source form was, and the source form was exactly the one you would have got from the defun/simple macro given here.
Notes
lambda as a macro
In ANSI CL, lambda is defined as a macro whose expansion is a suitable (function (lambda ...)) form:
> (macroexpand '(lambda (x) x))
#'(lambda (x) x)
t
> (car (macroexpand '(lambda (x) x)))
function
This means that you don't have to write (function (lambda ...)) yourself: you can rely on the macro definition of lambda doing it for you. Historically, lambda wasn't always a macro in CL: I can't find my copy of CLtL1, but I'm pretty certain it was not defined as one there. I'm reasonably sure that the macro definition of lambda arrived so that it was possible to write ISLisp-compatible programs on top of CL. It has to be in the language because lambda is in the CL package and so users can't portably define macros for it (although quite often they did define such a macro, or at least I did). I have not relied on this macro definition above.
defun/simple does not purport to be a proper clone of defun: its only purpose is to show how such a macro can be written. In particular it doesn't deal with declarations properly, I think: they need to be lifted out of the block & are not.
Elisp
Elisp is much more horrible than CL. In particular, in CL there is a well-defined function type, which is disjoint from lists:
> (typep '(lambda ()) 'function)
nil
> (typep '(lambda ()) 'list)
t
> (typep (function (lambda ())) 'function)
t
> (typep (function (lambda ())) 'list)
nil
(Note in particular that (function (lambda ())) is a function, not a list: function is doing its job of making a function.)
In elisp, however, an interpreted function is just a list whose car is lambda (caveat: if lexical binding is on this is not the case: it's then a list whose car is closure). So in elisp (without lexical binding):
ELISP> (function (lambda (x) x))
(lambda (x)
x)
And
ELISP> (defun foo (x) x)
foo
ELISP> (symbol-function 'foo)
(lambda (x)
x)
The elisp intepreter then just interprets this list, in just the way you could yourself. function in elisp is almost the same thing as quote.
But function isn't quite the same as quote in elisp: the byte-compiler knows that, when it comes across a form like (function (lambda ...)) that this is a function form, and it should byte-compile the body. So, we can look at the expansion of defun in elisp:
ELISP> (macroexpand '(defun foo (x) x))
(defalias 'foo
#'(lambda (x)
x))
(It turns out that defalias is the primitive thing now.)
But if I put this definition in a file, which I byte compile and load, then:
ELISP> (symbol-function 'foo)
#[(x)
"\207"
[x]
1]
And you can explore this a bit further: if you put this in a file:
(fset 'foo '(lambda (x) x))
and then byte compile and load that, then
ELISP> (symbol-function 'foo)
(lambda (x)
x)
So the byte compiler didn't do anything with foo because it didn't get the hint that it should. But foo is still a fine function:
ELISP> (foo 1)
1 (#o1, #x1, ?\C-a)
It just isn't compiled. This is also why, if writing elisp code with anonymous functions in it, you should use function (or equivalently #'). (And finally, of course, (function ...) does the right thing if lexical scoping is on.)
Other ways of making functions in CL
Finally, I've said above that function & specifically (function (lambda ...)) is the only primitive way to make new functions in CL. I'm not completely sure that's true, especially given CLOS (almost any CLOS will have some kind of class instances of which are functions but which can be subclassed). But it does not matter: it is a way and that's sufficient.
DEFUN is a defining macro. Macros transform code.
In Common Lisp:
(defun foo (a)
(+ a 42))
Above is a definition form, but it will be transformed by DEFUN into some other code.
The effect is similar to
(setf (symbol-function 'foo)
(lambda (a)
(block foo
(+ a 42))))
Above sets the function cell of the symbol FOO to a function. The BLOCK construct is added by SBCL, since in Common Lisp named functions defined by DEFUN create a BLOCK with the same name as the function name. This block name can then be used by RETURN-FROM to enable a non-local return from a specific function.
Additionally DEFUN does implementation specific things. Implementations also record development information: the source code, the location of the definition, etc.
Scheme has DEFINE:
(define (foo a)
(+ a 10))
This will set FOO to a function object.

Using special variables as macro input?

I want to make a macro for binding variables to values given a var-list and a val-list.
This is my code for it -
(defmacro let-bind (vars vals &body body)
`(let ,(loop for x in vars
for y in vals
collect `(,x ,y))
,#body))
While it works correct if called like (let-bind (a b) (1 2) ...), it doesn't seem to work when called like
(defvar vars '(a b))
(defvar vals '(1 2))
(let-bind vars vals ..)
Then I saw some effects for other of my macros too. I am a learner and cannot find what is wrong.
Basic problem: a macro sees code, not values. A function sees values, not code.
CL-USER 2 > (defvar *vars* '(a b))
*VARS*
CL-USER 3 > (defvar *vals* '(1 2))
*VALS*
CL-USER 4 > (defmacro let-bind (vars vals &body body)
(format t "~%the value of vars is: ~a~%" vars)
`(let ,(loop for x in vars
for y in vals
collect `(,x ,y))
,#body))
LET-BIND
CL-USER 5 > (let-bind *vars* *vals* t)
the value of vars is: *VARS*
Error: *VARS* (of type SYMBOL) is not of type LIST.
1 (abort) Return to top loop level 0.
You can see that the value of vars is *vars*. This is a symbol. Because the macro variables are bound to code fragments - not their values.
Thus in your macro you try to iterate over the symbol *vars*. But *vars* is a symbol and not a list.
You can now try to evaluate the symbol *vars* at macro expansion time. But that won't work also in general, since at macro expansion time *vars* may not have a value.
Your macro expands into a let form, but let expects at compile time real variables. You can't compute the variables for let at a later point in time. This would work only in some interpreted code where macros would be expanded at runtime - over and over.
If you’ve read the other answers then you know that you can’t read a runtime value from a compiletime macro (or rather, you can’t know the value it will have at runtime at compiletime as you can’t see the future). So let’s ask a different question: how can you bind the variables in your list known at runtime.
In the case where your list isn’t really variable and you just want to give it a single name you could use macroexpand:
(defun symbol-list-of (x env)
(etypecase x
(list x)
(symbol (macroexpand x env))))
(defmacro let-bind (vars vals &body body &environment env)
(let* ((vars (symbol-list-of vars env))
(syms (loop for () in vars collect gensym)))
`(destructuring-bind ,syms ,vals
(let ,(loop for sym in syms for bar in vars collect (list var sym)) ,#body))))
This would somewhat do what you want. It will symbol-macroexpand the first argument and evaluate the second.
What if you want to evaluate the first argument? Well we could try generating something that uses eval. As eval will evaluate in the null lexical environment (ie can’t refer to any external local variables), we would need to have eval generate a function to bind variables and then call another function. That is a function like (lambda (f) (let (...) (funcall f)). You would evaluate the expression to get that function and then call it with a function which does he body (but was not made by eval and so captures the enclosing scope). Note that this would mean that you could only bind dynamic variables.
What if you want to bind lexical variables? Well there is no way to go from symbol to the memory location of a variable at runtime in Common Lisp. A debugger might know how to do this. There is no way to get a list of variables in scope in a macro, although the compiler knows this. So you can’t generate a function to set a lexically bound symbol. And it would be even harder to do if you wanted to shadow the binding although you could maybe do it with some symbol-macrolet trickery if you knew every variable in scope.
But maybe there is a better way to do this for special variables and it turns out there is. It’s an obscure special form called progv. It has the same signature that you want let-bind to have except it works. link.

Common Lisp Lisp-1 macro

I am trying to emulate the single namespace of scheme within common lisp, with a macro (based on Doug Hoyte's) that expands to a lambda, where every use of an f! symbol (similar to Doug Hoyte's o! and g! symbols) in the function position expands to the same expression, but with funcall added in the function position of each invocation. For example:
(fplambda (f!z x) (f!z x x))
would expand to:
(LAMBDA (F!Z X) (FUNCALL F!Z X X))
The macro currently looks like this:
(defmacro fplambda (parms &body body)
(let ((syms (remove-duplicates
(remove-if-not #'f!-symbol-p
(flatten body)))))
`(lambda ,parms
(macrolet ,(mapcar
(lambda (f)
`(,f (&rest parmlist) `(funcall ,',f ',#parmlist)))
syms))
,#body)))
but given the above input, it expands (as far as I can see) to this:
(LAMBDA (F!F X)
(MACROLET ((F!F (&REST PARMLIST) `(FUNCALL ,'F!F ',#PARMLIST))))
(F!F X X))
In the macrolet definition, F!F should not be quoted or unquoted, and parmlist should just be unquoted. What is going on?
Thanks in advance!
Your definition is mostly right. You just made two pretty simple mistakes. The first one being a mismatched paren. The macrolet does not include the body (in the output the macrolet and the body are at the same level of indentation).
As for the nested backquote, the only mistake is the quote before parmlist. Other than that everything else is correct. The comma and quote before F!F is actually correct. From the hyperspec:
"An implementation is free to interpret a backquoted form F1 as any form F2 that, when evaluated, will produce a result that is the same under equal as the result implied by the above definition". Since the inner backquote has not been expanded yet, it does not have to be free of quotes and unquotes. The expression `(,'x) is actually the same as `(x).
Nested backquotes are notoriously complicated. What is probably the easiest way to understand them is to read Steele's explanation of them.
Edit:
The answer to your question about whether it is possible to use a fplambda expression in the function position is no. From the part of the hyperspec that deals with the evaluation of code: "If the car of the compound form is not a symbol, then that car must be a lambda expression, in which case the compound form is a lambda form.". Since the car of the form, (fplambda ...), is not a lambda expression, your code is no longer valid Common Lisp code.
There is a workaround to this that I figured out, but it's kind of ugly. You can define a reader macro that will allow you to write something like ([fplambda ...] ...) and have it read as
((LAMBDA (&REST #:G1030) (APPLY (FPLAMBDA ...) #:G1030)) ...)
which would do what you want. Here is code that will allow you to do that:
(set-macro-character #\[ 'bracket-reader)
(set-macro-character #\] (get-macro-character #\)))
(defun bracket-reader (stream char)
"Read in a bracket."
(declare (ignore char))
(let ((gargs (gensym)))
`(lambda (&rest ,gargs)
(apply ,(read-delimited-list #\] stream t)
,gargs))))
The only other solution I can think of would be to use some sort of code walker (I can't help you there).

lisp macro expand with partial eval

I have following code which confuse me now, I hope some can tell me the difference and how to fix this.
(defmacro tm(a)
`(concat ,(symbol-name a)))
(defun tf(a)
(list (quote concat) (symbol-name a)))
I just think they should be the same effect, but actually they seem not.
I try to following call:
CL-USER> (tf 'foo)
(CONCAT "FOO")
CL-USER> (tm 'foo)
value 'FOO is not of the expected type SYMBOL.
[Condition of type TYPE-ERROR]
So, what's the problem?
What i want is:
(tm 'foo) ==> (CONCAT "FOO")
The first problem is that 'foo is expanded by the reader to (quote foo), which is not a symbol, but a list. The macro tries to expand (tm (quote foo)). The list (quote foo) is passed as the parameter a to the macro expansion function, which tries to get its symbol-name. A list is not a valid argument for symbol-name. Therefore, your macro expansion fails.
The second problem is that while (tm foo) (note: no quote) does expand to (concat "FOO"), this form will then be executed by the REPL, so that this is also not the same as your tf function. This is not surprising, of course, because macros do different things than functions.
First, note that
`(concat ,(symbol-name a))
and
(list (quote concat) (symbol-name a))
do the exact same thing. They are equivalent pieces of code (backquote syntax isn't restricted to macro bodies!): Both construct a list whose first element is the symbol CONCAT and whose second element is the symbol name of whatever the variable A refers to.
Clearly, this only makes sense if A refers to a symbol, which, as Svante has pointed out, isn't the case in the macro call example.
You could, of course, extract the symbol from the list (QUOTE FOO), but that prevents you from calling the macro like this:
(let ((x 'foo))
(tm x))
which raises the question of why you would event want to force the user of the macro to explicitly quote the symbol where it needs to be a literal constant anyway.
Second, the way macros work is this: They take pieces of code (such as (QUOTE FOO)) as arguments and produce a new piece of code that, upon macroexpansion, (more or less) replaces the macro call in the source code. It is often useful to reuse macro arguments within the generated code by putting them where they are going to be evaluated later, such as in
(defmacro tm2 (a)
`(print (symbol-name ,a)))
Think about what this piece of code does and whether or not my let example above works now. That should get you on the right track.
Finally, a piece of advice: Avoid macros when a function will do. It will make life much easier for both the implementer and the user.

Creating a lambda from an s-expression

I have an s-expression bound to a variable in Common Lisp:
(defvar x '(+ a 2))
Now I want to create a function that when called, evaluates the expression in the scope in which it was defined. I've tried this:
(let ((a 4))
(lambda () (eval x)))
and
(let ((a 4))
(eval `(lambda () ,x)))
But both of these create a problem: EVAL will evaluate the code at the top level, so I can't capture variables contained in the expression. Note that I cannot put the LET form in the EVAL. Is there any solution?
EDIT: So if there is not solution to the EVAL problem, how else can it be done?
EDIT: There was a question about what exactly I am try to do. I am writing a compiler. I want to accept an s-expression with variables closed in the lexical environment where the expression is defined. It may indeed be better to write it as a macro.
You need to create code that has the necessary bindings. Wrap a LET around your code and bind every variable you want to make available in your code:
(defvar *x* '(+ a 2))
(let ((a 4))
(eval `(let ((a ,a))
,*x*)))
CLISP implements an extension to evaluate a form in the lexical environment. From the fact that it is an extension, I suspect you can't do that in a standard-compliant way.
(ext:eval-env x (ext:the-environment))
See http://clisp.cons.org/impnotes.html#eval-environ.
What is the actual problem that you want to solve? Most likely, you're trying to tackle it the wrong way. Lexical bindings are for things that appear lexically within their scope, not for random stuff you get from outside.
Maybe you want a dynamic closure? Such a thing doesn't exist in Common Lisp, although it does in some Lisp dialects (like Pico Lisp, as far as I understand).
Note that you can do the following, which is similar:
(defvar *a*)
(defvar *x* '(+ *a* 2)) ;'
(let ((a 10))
;; ...
(let ((*a* a))
(eval *x*)))
I advise you to think hard about whether you really want this, though.
In Common Lisp you can define *evalhook* Which allows you to pass an environment to (eval ...). *evalhook* is platform independent.
It is possible to use COMPILE to compile the expression into function and then use PROGV to FUNCALL the compiled function in the environment where variables are dynamically set. Or, better, use COMPILE to compile the expression into function that accepts variables.
Compile accepts the function definition as a list and turns it into function. In case of SBCL, this function is compiled into machine code and will execute efficiently.
First option (using compile and progv):
(defvar *fn* (compile nil '(lambda () (+ a 2)))
(progv '(a) '(4) (funcall *fn*))
=>
6
Second option:
(defvar *fn* (compile nil '(lambda (a) (+ a 2))))
(funcall *fn* 4)
=>
6