How do I copy a structure in Common Lisp? I created a structure like:
(defstruct state board player previous-move depth)
Board is a 2 dimension array. I tried doing:
(setf new-state state)
When I change something in new-state, the changes in the 2 dimension array also occur in state.
How can I create a copy of a structure like state and change it independently?
Common Lisp gives you two ways:
with DEFSTRUCT state there is a function copy-state defined.
the function COPY-STRUCTURE copies a structure
Note that these are shallow copies. Only the slot references get copied. There won't be a copy of the referenced data.
To copy the array, you would need to write a routine (possibly there are library routines).
It’s possible the following generic method may work (ie, produce a deep copy of a structure object), although it is not guaranteed to work in every Common Lisp implementation, and certainly is not portable. It does not conform to the Common Lisp Hyperspec, since it tries to apply class functions to structures. But it might be worth a try for personal use.
(defmethod deep-copy ((struct structure-object))
"Copy a structure recursively."
(let ((new-struct (copy-structure struct))
(slots (class-direct-slots (class-of struct))))
(dolist (slot slots)
(let ((slot-name (slot-definition-name slot)))
(setf (slot-value new-struct slot-name)
(deep-copy (slot-value struct slot-name)))))
new-struct))
Use it in the same way you would use copy-list--ie, (deep-copy my-lisp-object) -> my-lisp-object-copy. Note however, that this method is only one of several required, since deep-copy needs to recurse over the objects in the structure’s slots, the objects within those objects, etc, until the bottommost immutable objects are reached. These other methods are included in the post at https://codereview.stackexchange.com/questions/156392/generic-copy-function if needed. (Note also, that I’ve changed the name of the methods to deep-copy from ucopy—ie, universal copy). Good luck!
Another approach is to write your own copy function for a structure type, if you are not happy with the one automatically generated.
In order to do so, you first have to tell the defstruct macro to not create the copy function automatically.
(defstruct (foo (:copier nil))
(arr (make-array 10 :initial-element 0)))
;; now you can write your custom copy-foo function
(defun copy-foo (original)
(make-foo
:arr (copy-seq (foo-arr original))))
Related
I have this list of names and different languages
(setq l '((david spanish german)
(amanda italian spanish english)
(tom german french)))
I want to do the next with a function: for each language, I need every name relationed with every language.
For example, if I call the function with the list L:
(lenguages L)
I want to show this:
( (english (amanda))
(spanish (david amanda))
(italian (amanda))
(german(david tom))
(french(tom))
)
I have an idea of how to do this, but it shows just one item.
(defun lenguages(names)
(cond((null names) nil)
((list (cadar names) (list (caar names))))))
this last function only show (spanish (david))
An iteration-based task like this is best suited to Common Lisp's immensely powerful loop macro. You can read all the details about this macro in the GigaMonkeys book, but we'll just go over the parts you need for this problem here. Let's start with the function definition.
(defun lenguages (names)
...)
Inside this, we want to iterate over the provided list. We also want to collect some keys, so a hash table would be useful to have. Hash tables (called maps or dicts in many other languages) associate keys to values in a time-efficient way.
(loop with hash = (make-hash-table)
for entry in names
for name = (car entry)
do ...
finally ...)
The loop macro is very powerful and has a language all its own. The with clause declares a local variable, in this case a hash table. The first for defines an iteration variable. The loop will run with entry bound to each entry of names and will stop when it runs out of entries. The third line is another local variable, but unlike with, a for variable is rebound every time, so at each iteration name will be the first element of entry. The do block contains arbitrary Lisp code that will be executed each iteration, and finally contains a block of Lisp code to execute at the end of the loop.
Inside the do block, we want to add the person's name to the hash table entry for each language they know, so we need another loop to loop over the known languages.
(loop for lang in (cdr entry)
do (push name (gethash lang hash)))
This loop goes inside the do block of the outer one. For each language in the person's list of known languages, we want to prepend that person's name onto the hash value for that language. Normally, we would have to consider the case in which the hash key doesn't exist, but luckily for us Common Lisp defaults to nil if the hash key doesn't exist, and prepending an element to nil creates a one-element list, which is just what we want.
Now, when this loop is done, the hash table will contain all the languages and keys and lists of people who know them as values. This is the data that you want, but it's not in the format you want. In fact, if we put this in our finally block
(return hash)
We would get some semi-useful output* that tells us we're on the right track.
#S(HASH-TABLE :TEST FASTHASH-EQL ((TOM GERMAN FRENCH) . (TOM TOM))
((AMANDA ITALIAN SPANISH ENGLISH) . (AMANDA AMANDA AMANDA))
((DAVID SPANISH GERMAN) . (DAVID DAVID)))
Instead, let's do one more loop to convert this hash table to the list that you want it to be. Here's what we want in the finally block now.
(return (loop for key being the hash-keys of hash using (hash-value value)
collect (list key value)))
This uses the relatively obscure being syntax for the loop macro, which allows easy iteration over hash tables. You should read this as: for every key-value pair, collect a list containing the key followed by the value into a list, then return the accumulated list. This is yet another of the loop macros interesting features: it tries to provide primitives for common use cases such as accumulating values into a list. And it comes in handy in cases like this.
Here's the complete code block.
(defun lenguages (names)
(loop with hash = (make-hash-table)
for entry in names
for name = (car entry)
do (loop for lang in (cdr entry)
do (push name (gethash lang hash)))
finally (return (loop for key being the hash-keys of hash using (hash-value value)
collect (list key value)))))
That link I provided earlier is to the GigaMonkeys book on Common Lisp, which is available online for free. I strongly encourage reading through it, as it's an amazing reference for all things Common Lisp. Especially if you're just starting out, that book can really set you in the right direction.
* Your output format may vary on this. The implementation chooses how to output structs.
The other answer is fine: here is a version which does not use loop or intermediate hashtables, but instead builds the required association-list directly. It's worth comparing the efficiency of this against the hash-table-based one: it does a lot more searching down lists, but in practice, for small amounts of data such things are often faster (hashtables have nontrivial overhead in many implementations) and it will always use less storage as it builds no structure it does not return.
Note that:
this will return results in a different order in general (it has no dependency on hash ordering);
this will ensure there is only one occurrence of each person for each language: (languages '((david german german))) is ((german (david))) not ((german (david david))) -- it pays some performance cost (which could be ameliorated for large data using more hashtables) for doing this.
So, here it is:
(defun languages (people)
(let ((langs '())) ;the map we are building
(dolist (pl people langs)
(destructuring-bind (person . person-languages) pl
(dolist (lang person-languages)
(let ((entry (assoc lang langs)))
(if (not (null entry))
;; there's an entry for lang: add the person to it
(pushnew person (second entry))
;; there is no entry, create one with person in it
(setf langs `((,lang (,person)) ,#langs)))))))))
(Note also that the loop based version could use loop's destructuring, which might be a little clearer.)
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).
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!
I am building a mechanism to take an arbitrary CLOS object and return a hash from it (useful in my debugging experience).
However, I am not sure how to force a variable expansion. I sense that the solution lies with a correct use of gensym, but I'm not sure how.
;;helper macro
(defun class-slots-symbols (class-name)
"Returns a list of the symbols used in the class slots"
(mapcar 'closer-mop:slot-definition-name
(closer-mop:class-slots
(find-class class-name))))
;;macro that I am having difficulty with
(defmacro obj-to-hash (obj-inst)
"Reads an object, reflects over its slots, and returns a hash table of them"
`(let ((new-hash (make-hash-table))
(slot-list (class-slots-symbols (type-of ,obj-inst))))
;;The slot-list needs to expand out correctly in the with-slots form
(with-slots (slot-list) obj-inst
(loop for slot in slot-list do ;and also here
(format t "~a~&" slot)
(hashset new-hash (string slot) slot)))))
After a macroexpand-1, I find that that this expands into the following code (*bar* is a class object):
(macroexpand-1 '(obj-to-hash *bar*))
LET ((NEW-HASH (MAKE-HASH-TABLE))
(SLOT-LIST (CLASS-SLOTS-SYMBOLS (TYPE-OF *BAR*))))
(WITH-SLOTS (SLOT-LIST) ;; <-- this needs to be expanded to *bar*'s slots
*BAR*
(LOOP FOR SLOT IN SLOT-LIST ;;<-- not so important
DO (FORMAT T "~a~&" SLOT) (HASHSET NEW-HASH (STRING SLOT) SLOT))))
Obviously, the problem is that slot-list is not being expanded. Less obvious (to me) is the solution.
Followup: After Rainer pointed me in the right direction:
(defun class-slots-symbols (class-instance)
"Returns a list of the symbols used in the class slots"
(mapcar 'closer-mop:slot-definition-name
(closer-mop:class-slots
(class-of class-instance))))
(defun object-to-hash (obj)
"Reflects over the slots of `obj`, and returns a hash table mapping
slots to their values"
(let ((new-hash (make-hash-table))
(slot-list (class-slots-symbols obj)))
(loop for slot in slot-list do
(hashset new-hash (string slot)
(slot-value obj slot)))
new-hash))
Just looking at it I can see no reason why this should be a macro. Rewriting it as a function will save you a lot of trouble.
The use of WITH-SLOTS is not possible they way you try it. The object is not known in general until runtime. The compiler needs to know the slots of the object at compile time already. You need to use SLOT-VALUE and look up the slot value at runtime.
You are thinking in many ways too complicated and your code is slightly confused. You can get rid of some confusion by following simple rules and avoiding some wording.
Let's look at your code:
First, it is not a helper macro, since what follows is a function.
;;helper macro
(defun class-slots-symbols (class-name)
Why take a class name? Why not use the class itself? Classes are first class objects. Write function with obvious interfaces. Elementary functions should work on the basic data types.
"Returns a list of the symbols used in the class slots"
In the class slots no symbols are used. slots have names, one can get this symbol.
(mapcar 'closer-mop:slot-definition-name
(closer-mop:class-slots
(find-class class-name))))
It is no wonder you have a problem with this macro. It is simply because it should be a function, not a macro. Macros are for source transformation. All you need is a simple computation, so no macro is needed
;;macro that I am having difficulty with
(defmacro obj-to-hash (obj-inst)
Poor wording: obj-inst. Either name it object or instance. Not both.
"Reads an object, reflects over its slots, and returns a hash table of them"
Poor documentation: you don't READ anything. Read is an I/O operation and in your code is none. You are talking about an 'object', but above you have something like 'obj-inst'. Why talk about the same thing in two different ways? You may want to document what the hash table actual maps. From which keys to which values?
`(let ((new-hash (make-hash-table))
new-hash is also a poor name. Basically the thing is a hash-table.
(slot-list (class-slots-symbols (type-of ,obj-inst))))
Why TYPE-OF and then later in the helper function call FIND-CLASS? Common Lisp has CLASS-OF, which returns the class directly.
;;The slot-list needs to expand out correctly in the with-slots form
(with-slots (slot-list) obj-inst
Above won't work since WITH-SLOTS expects slot names at compile time, not a slot-list.
(loop for slot in slot-list do ;and also here
(format t "~a~&" slot)
(hashset new-hash (string slot) slot)
HASHSET is not needed, unless it does something special. The usual way to set values is via SETF. SETF takes the form to read a place and the form to compute a value. That's all. It works for all kinds of data structures. One never needs to remember again how the writer function looks like (name, parameter list, ...).
))))
Here is my version:
Note that I use the package CLOS, you may want to use your package CLOSER-MOP
(defun class-slots-symbols (class)
"Returns a list of the symbol names of the class slots"
(mapcar 'clos:slot-definition-name
(clos:class-slots class)))
Above is a simple function taking a class and returning the list of slot names.
Next, we have a simple function, which in this form has been written a million times in Common Lisp:
(defun object-to-hash (object)
"returns a hashtable with the object's slots as keys and slot-values as values"
(let ((hash-table (make-hash-table)))
(loop for slot-name in (class-slots-symbols (class-of object))
do (setf (gethash slot-name hash-table)
(string (slot-value object slot-name))))
hash-table))
We can also rewrite it to slightly older style Lisp:
(defun object-to-hash (object &aux (hash-table (make-hash-table)))
"returns a hashtable with the object's slots as keys
and string versions of the slot-values as values"
(dolist (slot-name (class-slots-symbols (class-of object)) hash-table)
(setf (gethash slot-name hash-table)
(string (slot-value object slot-name)))))
Above is much simpler and has the whole confusion about macros, generating code, compile time information vs. runtime, ... removed. It is much easier to understand, maintain and debug.
So... I'm new to scheme r6rs, and am learning macros. Can somebody explain to me what is meant by 'hygiene'?
Thanks in advance.
Hygiene is often used in the context of macros. A hygienic macro doesn't use variable names that can risk interfering with the code under expansion. Here is an example. Let's say we want to define the or special form with a macro. Intuitively,
(or a b c ... d) would expand to something like (let ((tmp a)) (if tmp a (or b c ... d))). (I am omitting the empty (or) case for simplicity.)
Now, if the name tmp was actually added in the code like in the above sketched expansion, it would be not hygienic, and bad because it might interfere with another variable with the same name. Say, we wanted to evaluate
(let ((tmp 1)) (or #f tmp))
Using our intuitive expansion, this would become
(let ((tmp 1)) (let ((tmp #f)) (if tmp (or tmp)))
The tmp from the macro shadows the outer-most tmp, and so the result is #f instead of 1.
Now, if the macro was hygienic (and in Scheme, it's automatically the case when using syntax-rules), then instead of using the name tmp for the expansion, you would use a symbol that is guaranteed not to appear anywhere else in the code. You can use gensym in Common Lisp.
Paul Graham's On Lisp has advanced material on macros.
If you imagine that a macro is simply expanded into the place where it is used, then you can also imagine that if you use a variable a in your macro, there might already be a variable a defined at the place where that macro is used.
This is not the a that you want!
A macro system in which something like this cannot happen, is called hygienic.
There are several ways to deal with this problem. One way is simply to use very long, very cryptic, very unpredictable variable names in your macros.
A slightly more refined version of this is the gensym approach used by some other macro systems: instead of you, the programmer coming up with a very long, very cryptic, very unpredictable variable name, you can call the gensym function which generates a very long, very cryptic, very unpredictable and unique variable name for you.
And like I said, in a hygienic macro system, such collisions cannot happen in the first place. How to make a macro system hygienic is an interesting question in itself, and the Scheme community has spent several decades on this question, and they keep coming up with better and better ways to do it.
I'm so glad to know that this language is still being used! Hygienic code is code that when injected (via a macro) does not cause conflicts with existing variables.
There is lots of good information on Wikipedia about this: http://en.wikipedia.org/wiki/Hygienic_macro
Here's what I found. Explaining what it means is another matter altogether!
http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-1.html#node_toc_node_sec_12.1
Macros transform code: they take one bit of code and transform it into something else. As part of that transformation, they may surround that code with more code. If the original code references a variable a, and the code that's added around it defines a new version of a, then the original code won't work as expected because it will be accessing the wrong a: if
(myfunc a)
is the original code, which expects a to be an integer, and the macro takes X and transforms it to
(let ((a nil)) X)
Then the macro will work fine for
(myfunc b)
but (myfunc a) will get transformed to
(let ((a nil)) (myfunc a))
which won't work because myfunc will be applied to nil rather than the integer it is expecting.
A hygienic macro avoids this problem of the wrong variable getting accessed (and a similar problem the other way round), by ensuring that the names used are unique.
Wikipedia has a good explanation of hygienic macros.
Apart from all the things mentioned, there is one important other thing to Scheme's hygienic macros, which follow from the lexical scope.
Say we have:
(syntax-rules () ((_ a b) (+ a b)))
As part of a macro, surely it will insert the +, it will also insert it when there's a + already there, but then another symbol which has the same meaning as +. It binds symbols to the value they had in the lexical environment in which the syntax-rules lies, not where it is applied, we are lexically scoped after all. It will most likely insert a completely new symbol there, but one which is globally bound to the same meaning as + is at the place the macro is defined. This is most handy when we use a construct like:
(let ((+ *))
; piece of code that is transformed
)
The writer, or user of the macro thus needn't be occupied with ensuring its use goes well.