pushnew without place support. Is it considered a destructive macro? - lisp

One function and one macro
;; I am sorry for the confusing function name.
;; As one answer suggests, cons-if-not-member is the better name.
(defun cons-if-member (element list)
(if (member element list)
list
(cons element list)))
(defmacro pushnew-no-bells (element list)
"pushnew without place support"
`(setq ,list (cons-if-member ,element ,list)))
(let ((xx (list 1 2)))
(pushnew-no-bells 0 xx)
xx)
I do not know which of the following is correct:
cons-if-member is a non-destructive function and pushnew-no-bells is a destructive macro.
Both are non-destructive.
cons-if-member is a non-destructive function and the adjectives "destructive" and "non-destructive" do not apply to macros.
none of the above
I do not have any idea on whether pushnew is considered destructive or not either, but I wanted to make things simple by dropping place support first.

pushnew changes the value of it's place-form (2nd argument), so it is destructive: it changes something "in place" instead of just creating a new object (which may share structure with an existing one). Your cons-if-member (which would better be called cons-unless-member or cons-if-not-member) does not modify anything "in place", so it's actually non-destructive.
Note, BTW., that you cannot really exclude "general place" support, due to the presence of symbol macros. Observe:
(defclass foo ()
((x :initform nil)))
(let ((instance (make-instance 'foo)))
(with-slots (x) instance
(pushnew-no-bells 1 x))
(format t "~&Now: ~S~%" (slot-value instance 'x)))

cons-if-member is not destructive. It is also roughly equivalent to ADJOIN. pushnew-no-bells modifies a place, but does not modify the structure of the list onto which an element might be pushed. However, it can modify the structure of other lists, because you could use it as (let ((list (list 1 2 3 4))) (pushnew-no-bells '1 (cddr list))). (Also, the form list will be evaluated twice, which is not good (but also not the main point of this question/answer).) This is destructive in the sense that it modifies that place, but it is not destructive in the sense that, e.g., nreverse is (nreverse can change the entire structure of a cons list).
The Hyperspec doesn't make quite the same distinction between destructive and non-destructive. The spec for ADJOIN, for instance, just says what it does
Tests whether item is the same as an existing element of list. If the item is not an existing element, adjoin adds it to list (as if by cons) and returns the resulting list; otherwise, nothing is added and the original list is returned.
and omits any mention of side effects. The documentation for PUSHNEW, on the other hand, mentions in its syntax section that it requires a place
pushnew item place &key key test test-not
=> new-place-value
and the decription mentions that it has side effects:.
the new list is stored in place. [emphasis added] …
Side Effects: The contents of place may be modified.
While destructive and non-destructive capture some general ideas about how things are implemented, actual implementations tend to be a little bit more subtle, because the programmer is concerned with what things might be destructively modified, and what sort of state might be changed.
The approach that you are using (that is, making a functional implementation of some operation and then implementing a modifying macro on top of it), however, is very good, as it will help you document what functions and macros will have side effects. It will help anyone reading that documentation understand what the intended side effects of the macro is (just compute what the function would compute, and then store it back to the place). If you're doing much of this (actually, if you're doing any of this), you should also probably take a good look at DEFINE-MODIFY-MACRO which makes implementing these kinds of function/macro pairs very easy, and will help you avoid common pitfalls (like the double evaluation of list above).

Related

`apply` or `funcall` for macros instead of functions

In Lisp, a function's arguments are evaluated first before entering the function body. Macro arguments stay not evaluated.
But sometimes, one wants to inject code pieces stored in variables into a macro. This means evaluating the argument for the macro first, and then apply the macro-of-choice on this evaluated result.
One has to resort to
(eval `(macro ,arg))
To achieve this - but eval does not behave correctly in different environments.
The best thing would be, if one could do:
(apply macro (list arg))
or
(funcall macro arg)
But since the macro is not a function this doesn't work.
Is it possible to achieve something like this? - To circumvent that problem oder to make the macro available in the functions namespace?
Or am I missing some other ways to solve such problems?
I came to this question while trying to answer How to produce HTML from a list. but also in Generate TYPECASE with macro in common lisp, Evaluate arguments passed to a macro that generates functions in lisp, and How to convert a list to code/lambda in scheme?. But I always thought while answering them it would be good to have an apply or funcall-like function which can take macros.
It is not clear what you are trying to do, although it is almost certain that you are confused about something. In particular if you are calling eval inside macroexpansions then in almost all cases you are doing something both seriously wrong and seriously dangerous. I can't ever think of a case where I've wanted macros which expand to things including eval and I have written Lisp for a very very long time.
That being said, here is how you call the function associated with a macro, and why it is very seldom what you want to do.
Macros are simply functions whose domain and range is source code: they are compilers from a language to another language. It is perfectly possible to call the function associated with a macro, but what that function will return is source code, and what you will then need to do with that source code is evaluate it. If you want a function which deals with run-time data which is not source code, then you need that function, and you can't turn a macro into that function by some magic trick which seems to be what you want to do: that magic trick does not, and can not, exist.
So for instance if I have a macro
(defmacro with-x (&body forms)
`(let ((x 1))
,#forms))
Then I can call its macro function on a bit of source code:
> (funcall (macro-function 'with-x)
'(with-x (print "foo")) nil)
(let ((x 1)) (print "foo"))
But the result of this is another bit of source code: I need to compile or evaluate it, and nothing I can do will get around this.
Indeed in (almost?) all cases this is just the same as macroexpand-1):
> (macroexpand-1 '(with-x (print "foo")))
(let ((x 1)) (print "foo"))
t
And you can probably write macroexpand-1 in terms of macro-function:
(defun macroexpand-1/equivalent (form &optional (env nil))
(if (and (consp form)
(symbolp (first form))
(macro-function (first form)))
(values (funcall (macro-function (first form)) form env)
t)
(values form nil)))
So, if the result of calling a macro is source code, what do you do with that source code to get a result which is not source code? Well, you must evaluate it. And then, well, since the evaluator expands macros for you anyway, you might as well just write something like
(defun evaluate-with-x (code)
(funcall (compile nil `(lambda ()
(with-x ,#code)))))
So you didn't need to call the macro's function in any case. And this is not the magic trick which turns macros into functions dealing with data which is not source code: it is a terrible horror which is entirely made of exploding parts.
A concrete example: CL-WHO
It looks like this question might have its origins in this one and the underlying problem there is that that's not what CL-WHO does. In particular it is a confusion to think that something like CL-WHO is a tool for taking some kind of list and turning it into HTML. It's not: it's a tool for taking the source code of a language which is built on CL but includes a way of expressing HTML output mingled with CL code, and compiles it into CL code which will do the same thing. It happens to be the case that CL source code is expressed as lists & symbols, but CL-WHO isn't really about that: it's a compiler from, if you like, 'the CL-WHO language' to CL.
So, let's try the trick we tried above and see why it's a disaster:
(defun form->html/insane (form)
(funcall
(compile nil `(lambda ()
(with-html-output-to-string (,(make-symbol "O"))
,#form)))))
And you might, if you did not look at this too closely, think that this function does in fact do the magic trick:
> (form->html/insane '(:p ((:a :href "foo") "the foo")))
"<p></p><a href='foo'>the foo</a>"
But it doesn't. What happens if we call form->html/insane on this perfectly innocuous list:
(:p (uiop/run-program:run-program "rm -rf $HOME" :output t))
Hint: don't call form->html/insane on this list if you don't have very good backups.
CL-WHO is an implementation of a programming language which is a strict superset of CL: if you try to turn it into a function to turn lists into HTML you end up with something involving the same nuclear weapon you tinker with every time you call eval, except that nuclear weapon is hidden inside a locked cupboard where you can't see it. But it doesn't care about that: if you set it off it will still reduce everything within a few miles to radioactive ash and rubble.
So if you want a tool which will turn lists – lists which aren't source code – into HTML then write that tool. CL-WHO might have the guts of such a tool in its implemenentation, but you can't use it as it is.
And this is the same problem you face whenever you are trying to abuse macros this way: the result of calling a macro's function is Lisp source code, and to evaluate that source code you need eval or an equivalent of eval. And eval is not only not a terrible solution to almost any problem: it's also a nuclear weapon. There are, perhaps problems for which nuclear weapons are good solutions, but they are few and far between.

With case, which is the best of these methods for expressing the cases?

These all work:
(defun testcaseexpr (thecase)
(case thecase
('foo (format t "matched foo"))
(bar (format t "matched bar"))
((funk) (format t "matched funky"))))
Which of these three expressions is considered the idiomatic way? And perhaps as a side point, why are they all working, when clearly they are not the same syntax. In fact in other contexts they have different semantics completely. A list (funk) is certainly not the same as a quoted atom, 'foo. Yet just passing in the words foo bar and funk all work the same.
First, note that you've actually only got two cases here. 'foo is expanded by the reader as (quote foo), so your code is equivalent to
(defun testcaseexpr (thecase)
(case thecase
((quote foo) (format t "matched foo"))
(bar (format t "matched bar"))
((funk) (format t "matched funky"))))
wherein the first and third cases have the same structure; the keys part of the clause is a list of objects.
Perhaps this question is off-topic, since it's asking for the “best”, and that might be primarily opinion based. I agree with the points made in wvxvw's answer, but I tend to use the style you've shown in the third case almost exclusively. I've got a couple reasons for this:
It's the most general form.
It's the most general form. In the documentation for case, we read that in an normal-clause ::= (keys form*) keys is a designator for a list of keys. This means that a clause like (2 (print 'two)) is equivalent to ((2) (print 'two)). You never lose anything by using a list instead of a non-list, but if you have some clauses with multiple objects and some with single objects, you'll have consistent syntax for all of them. E.g., you can have
(case operator
((and or) ...)
((if iff) ...)
((not) ...))
It's harder to mess up.
It makes it harder to mess up the special cases of t and otherwise. The documentation says about keys that (emphasis added):
keys—a designator for a list of objects. In the case of case, the
symbols t and otherwise may not be used as the keys designator. To
refer to these symbols by themselves as keys, the designators (t) and
(otherwise), respectively, must be used instead.
In practice, some implementations will let you use t and otherwise as keys in normal-clauses, even though it seems like this shouldn't be allowed. E.g., in SBCL:
CL-USER> (macroexpand-1 '(case keyform
(otherwise 'a)
(otherwise 'b)))
(LET ((#:G962 KEYFORM))
(DECLARE (IGNORABLE #:G962))
(COND ((EQL #:G962 'OTHERWISE) NIL 'A)
(T NIL 'B)))
Using explicit lists removes any ambiguity about what you're trying to do. Even though t and otherwise are called out specifically, keys is a list designator, which means that nil (an atom and a list) needs some special consideration. Will the following code produce a or b? (Can you tell without testing it or checking the spec? This case is actually highlighted in the examples.)
(case nil
(nil 'a)
(otherwise 'b))
It returns b. To return a, the first normal-clause would have to be ((nil) 'a).
Conclusion
If you always make sure that keys is a list, you'll:
end up with more consistent looking code;
avoid edge-case bugs (especially if you're writing macros that expand into case); and
make your intentions clearer.
Second :)
First is never used, unless you expand a macro into something like it by accident, and third is used when you have more then one matching symbol (a fall-through case).

Iteration beyond while and maphash?

I'm trying to write a small system of macros to do iterative tasks in Emacs Lisp. I had taken it for granted that there is nothing beyond while loop. No more primitives or some hidden features, but I decided, I'd better ask.
By "hidden features" I mean something akin to tagbody in Common Lisp, i.e. the very primitive form to model the code in terms of blocks, jumps and labels. Are there any such thing in eLisp? Not even in any "hackish" way, like, for example, through the bytecode? Of course, I know about (catch ... (throw ... )) construct, but it is not quite the same, because it only allows jumping "backwards", but never forward. I also assumed it is a rather complex construct, not suitable for building fast iteration primitives.
Another thing that bugs me is that there doesn't seem to be a way to create an iterator for hash-tables. I.e. a hash-table must be itereated using maphash and once you exit the maphash function, there's no coming back to where you left it. So far I understand, it has to do something like, exporting a vector of keys and a vector of values and iterating over these, but there doesn't seem to be a way to get hold of these vectors / lists / whichever those are. Or am I again wrong?
I've looked into how cl package generates code for loop and dotimes / dolist / do, but they just use while or maphash, whichever is appropriate, and, frankly, I'm not so fond of their code... More than that, if, say, in the loop there are two for-as-hash clauses, they simply ignore the first (you don't even get a warning for that) and generate code for the second :|
Any chance there are some tricks to get hold of these iteration primitives from the user code in eLisp? If not, how feasible it is, and is it really, to write an extension in C?
You can tagbody as a macro:
(defmacro cl-tagbody (&rest tags-or-stmts)
(let ((blocks '()))
(let ((block (list 'cl--preamble)))
(dolist (tag-or-stmt tags-or-stmts)
(if (consp tag-or-stmt) (push tag-or-stmt block)
;; Add a "go to next block" to implement the fallthrough.
(push (nreverse (cons `(go ,tag-or-stmt) block)) blocks)
(setq block (list tag-or-stmt))))
(push (nreverse (cons `(go cl--exit) block)) blocks))
(let ((catch-tag (make-symbol "cl--tagbody-tag")))
(macroexpand-all
`(let ((next-tag 'cl--preamble))
(while
(not (eq (setq next-tag
(catch ',catch-tag
(cl-case next-tag
,#blocks)))
'cl--exit))))
`((go . (lambda (tag) `(throw ',catch-tag ',tag)))
,#macroexpand-all-environment)))))
1. Other looping constructs?
The only general-purpose built-in looping construct in Emacs Lisp is while (see eval.c). The macros dolist and dotimes (in subr.el) are both implemented using while.
There are also built-in functions for mapping over various data structures: mapatoms, mapc, mapcar, map-char-table, mapconcat, maphash, and map-keymap. But these are implemented in such a way that you can't interleave their execution with other Lisp code (see for example maphash in fns.c). If you want to loop over two such data structures, you have to loop over one and then over the other.
So I think you're basically out of luck.
2. Extensions?
Emacs is deliberately designed not to have dynamic C-level extensions, to make it more difficult for someone to mount an "embrace and extend" attack on the freedom of Emacs users (see the emacs-devel thread starting here, for example).
So if you want to add C-level functionality, you have to edit the source code. Good luck!

Common Lisp, reference to value and actual value

Consider this piece of code:
(defvar lst '(1 1))
(defmacro get-x (x lst)
`(nth ,x ,lst))
(defun get-y (y lst)
(nth y lst))
Now let us assume that I want to change the value of the elements of the list called lst, the car with get-x and the cdr with get-y.
As I try to change the value with get-x (with setf) everything goes fine but if I try it with get-y it signals an error (shortened):
; caught STYLE-WARNING:
; undefined function: (SETF GET-STUFF)
Why does this happen?
I myself suspect that this happens because the macro simply expands and the function nth simply returns a reference to the value of an element in the list and the function on the other hand evaluates the function-call to nth and returns the value of the referenced value (sounds confusing).
Am I correct in my suspicions?
If I am correct then how will one know what is simply a reference to a value and an actual value?
The error does not happen with the macro version, because, as you assumed, the expression (setf (get-x some-x some-list) some-value) will be expanded (at compile-time) into something like (setf (nth some-x some-list) some-value) (not really, but the details of setf-expansion are complex), and the compiler knows, how to deal with that (i.e., there is a suitable setf expander defined for function nth).
However, in the case of get-y, the compiler has no setf expander, unless you provide one. The easiest way to do so would be
(defun (setf get-y) (new-value x ls) ; Note the function's name: setf get-y
(setf (nth x ls) new-value))
Note, that there are a few conventions regarding setf-expanders:
The new value is always provided as the first argument to the setf function
All setf functions are supposed to return the new value as their result (as this is, what the entire setf form is supposed to return)
There is, BTW, no such concept as a "reference" in Common Lisp (at least not in the C++ sense), though there once were Lisp dialects which had locatives. Generalized place forms (ie., setf and its machinery) work very differently from plain C++ style references. See the CLHS, if you are curious about the details.
SETF is a macro.
The idea is that to set and read elements from data structures are two operations, but usually require two different names (or maybe even something more complex). SETF now enables you to use just one name for both:
(get-something x)
Above reads a datastructure. The inverse then simply is:
(setf (get-something x) :foobar)
Above sets the datastructure at X with :FOOBAR.
SETF does not treat (get-something x) as a reference or something like that. It just has a database of inverse operations for each operation. If you use GET-SOMETHING, it knows what the inverse operation is.
How does SETF know it? Simple: you have to tell it.
For The NTH operation, SETF knows how to set the nth element. That's builtin into Common Lisp.
For your own GET-Y operation SETF does not have that information. You have to tell it. See the Common Lisp HyperSpec for examples. One example is to use DEFUN and (SETF GET-Y) as a function name.
Also note following style problems with your example:
lst is not a good name for a DEFVAR variable. Use *list* as a name to make clear that it is a special variable declared by DEFVAR (or similar).
'(1 2) is a literal constant. If you write a Common Lisp program, the effects of changing it are undefined. If you want to change a list later, you should cons it with LIST or something like COPY-LIST.

My first Lisp macro; is it leaky?

I've been working through Practical Common Lisp and as an exercise decided to write a macro to determine if a number is a multiple of another number:
(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))
so that :
(multp 40 10)
evaluates to true whilst
(multp 40 13)
does not
The question is does this macro leak in some way? Also is this "good" Lisp? Is there already an existing function/macro that I could have used?
Siebel gives an extensive rundown (for simple cases anyway) of possible sources of leaks, and there aren't any of those here. Both value and factor are evaluated only once and in order, and rem doesn't have any side effects.
This is not good Lisp though, because there's no reason to use a macro in this case. A function
(defun multp (value factor)
(zerop (rem value factor)))
is identical for all practical purposes. (Note the use of zerop. I think it makes things clearer in this case, but in cases where you need to highlight, that the value you're testing might still be meaningful if it's something other then zero, (= ... 0) might be better)
Your macro looks fine to me. I don't know what a leaky macro is, but yours is pretty straightforward and doesn't require any gensyms. As far as if this is "good" Lisp, my rule of thumb is to use a macro only when a function won't do, and in this case a function can be used in place of your macro. However, if this solution works for you there's no reason not to use it.
Well, in principle, a user could do this:
(flet ((= (&rest args) nil))
(multp 40 10))
which would evaluate to NIL... except that ANSI CL makes it illegal to rebind most standard symbols, including CL:=, so you're on the safe side in this particular case.
In generial, of course, you should be aware of both referential untransparency (capturing identifiers from the context the macro is expanded in) and macro unhygiene (leaking identifiers to expanded code).
No, no symbol introduced in the macro's "lexical closure" is released to the outside.
Note that leaking isn't NECESSARILY a bad thing, even if accidental leaking almost always is. For one project I worked on, I found that a macro similar to this was useful:
(defmacro ana-and (&rest forms)
(loop for form in (reverse forms)
for completion = form then `(let ((it ,form))
(when it
,completion))
finally (return completion)))
This allowed me to get "short-circuiting" of things needed to be done in sequence, with arguments carried over from previous calls in the sequence (and a failure signalled by returning NIL). The specific context this code is from is for a hand-written parser for a configuration file that has a cobbled-together-enough syntax that writing a proper parser using a parser generator was more work than hand-rolling.