LISP modify list passed as argument - lisp

So i got this function that receives a list as an argument
(defun do-transf (lst)
...
my initial lst is ((NIL NIL) (NIL NIL))
but in the end i want the lst becomes
(NIL NIL NIL NIL)
example
(defvar a (list (list NIL NIL) (list NIL NIL)))
(do-transf a)
(NIL NIL NIL NIL) -> gives the right answer but when i call the list this isnt the answer
a
((NIL NIL) (NIL NIL)) -> i dont want this

Your post suggests that you wish to do list concatenation, i.e. append lists to another.
As such, try this:
(defvar a (list (list NIL NIL) (list NIL NIL)))
(apply #'append a)
This outputs:
(NIL NIL NIL NIL)
Short, simple, sweet.
UPDATE:
Since you want destructive behavior (that is, modification of the original value of a):
(setq a (apply #'append a))
Now, a is set to this new value (from ((NIL NIL) (NIL NIL))):
(NIL NIL NIL NIL)

Typically, lisp functions don't mutate the data they operate on. This is not a required property, but it does make it much easier writing and reasoning about large code bases.
So, what typically happens is that a function will return a copy of the new data, that can then replace the old value in a variable, at the discretion of the caller.
Even when functions destructively modify data structures, they tend to return the new resulting value.
If we look at the following code:
(defvar *example* '(delete 2 3 4))
=> *example*
(delete 'delete *example*)
=> (2 3 4)
*example*
=> (delete 2 3 4)
This is because there is no way for the function to destructively modify *example* so it loses the first element, so even when you are using destructive, mutating functions, they need to return a value suitable for storing back into the variable that the input came from.

Try using flatten..
(defvar a (flatten (list (list NIL NIL) (list NIL NIL))))

Related

LISP - Replace values in a list

I have a list of nils (NIL NIL NIL NIL) and i need to add two X in place of the two first NILs, so it becomes (X X NIL NIL).
I have the following code:
(cons x (cons x (cons (cdr '(NIL NIL NIL NIL))nil)))
But this way it returns
(X X (NIL NIL))
Those parenteses need to be removed, and i don't know how. Can someone help me?
Thanks
If you pass a list to the first argument of cons then you are making a nested list. First lets say we make your initial list and the symbol x variables:
(defparameter *nils* '(nil nil nil nil))
*nils* ; ==> (nil nil nil nil)
(defparameter *x* 'x)
*x* ; ==> x
So how do we remove the two first. Well we can remove one with (cdr *nils*) so that means we can do it twice:
(cdr (cdr *nils*))
; ==> (nil nil)
Actually more than one car and cdr accessor has a shorthand upto 5 combinations. The shorthand is just starting with c and do the a/d's and end with r like this:
(cddr *nils*)
; ==> (nil nil)
Goodie, how do we add *x* in front of that? Well cons is defines as making an element in front of the second argument, thus (cons *x* (cddr *nils*)) will make(x nil nil). Again if you want to have anotherx` in front of that you do the same with the firt result:
(cons *x* (cons *x* (cddr *nils*)))
; ==> (x x nil nil)
Using list* is like nested cons with a tail in the end. Thus the above code can be replaced with:
(list* *x* *x* (cddr *nils*))
; ==> (x x nil nil)
Now replacing the variables the expression that was stored as their value (substitution method):
(list* 'x 'x (cddr '(nil nil nil nil)))
; ==> (x x nil nil)
(list* X X (nthcdr 2 your-list))
The function NTHCDR returns the list with two first elements dropped & the function LIST* returns a new list appending specified items at the front.
Observe that thus you obtain a new list rather then modify the original one. If you really want to modify the original list (this may very well be a bad idea, proceed with caution), you can just make the assignment:
(setf (first your-list) 'X)
(setf (second your-list) 'X)
Modifying a list like this may result in modifications of seemingly unrelated data. It is not compatible with the quoted literal list, anyway.

Changing copies of lists in LISP

In LISP, I have a function that is passed a list. I would like to change an element of this list without changing the original list. Normally, I would use copy-list to create the local copy of the list which I will change, but this doesn't seem to be working:
CL-USER> (defun test (item)
(let ((copy (copy-list item)))
(setf (nth 0 (nth 0 (nth 0 copy))) t)
(print item)
(print copy)))
CL-USER> (defparameter item `(((NIL NIL) (NIL NIL) (NIL NIL))
((NIL NIL NIL) (NIL NIL NIL))
((3 3) (NIL NIL))))
CL-USER> (test item)
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
CL-USER> item
(((T NIL) (NIL NIL) (NIL NIL)) ((NIL NIL NIL) (NIL NIL NIL)) ((3 3) (NIL NIL)))
As you can see, the value of item was changed by test even though I copied the list into a local variable and changed the local copy. This seems to be a symptom of using nth. If I use a single call of car rather than the repeated call to nth, the function works as expected and the item is unchanged after the call.
Why does nth behave like this and how can I continue to use nth without altering the value passed to test?
I am using Common Lisp.
Short answer: use cl:copy-tree
You probably want to copy the whole tree with copy-tree. The copy made by copy-list only generates new "backbone"; you get a new list, but with the same elements. Copy-tree will copy all the cons-tree structure that makes up the tree.
Long answer: list structure vs. tree structure
The background here is referenced in the documentation. From the HyperSpec:
Function COPY-LIST
Only the list structure of list is copied; the elements of the
resulting list are the same as the corresponding elements of the given
list.
That glossary entry for list structure is important:
list structure n. (of a list) the set of conses that make up the list.
Note that while the car component of each such cons is part of the
list structure, the objects that are elements of the list (i.e., the
objects that are the cars of each cons in the list) are not
themselves part of its list structure, even if they are conses, except
in the (circular) case where the list actually contains one of its
tails as an element. (The list structure of a list is sometimes
redundantly referred to as its "top-level list structure" in order
to emphasize that any conses that are elements of the list are not
involved.)
As a very simple example, we can exploit the fact that *print-circle* will show us common substructure:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '((a b c) (d e f))))
(list l (copy-list l)))
;=> ((#1=(A B C) #2=(D E F)) (#1# #2#))
CL-USER> (let ((l '((a b c) (d e f))))
(list l (copy-tree l)))
;=> (((A B C) (D E F)) ((A B C) (D E F)))
The HyperSpec entry on copy-tree doesn't link to tree structure, but there is a glossary entry:
tree structure n. (of a tree) the set of conses that make up the
tree. Note that while the car component of each such cons is part
of the tree structure, the objects that are the cars of each cons
in the tree are not themselves part of its tree structure unless they
are also conses.
That second sentence is a bit strange, but it's probably just in there as a minimally adjusted copy and paste of the list structure entry. See my answer to Definition of tree structure in Lisp for a bit more about that.

Lisp (null (QUOTE NIL)) returns NIL

I am new to lisp and I'm trying to a simple check to see if a list is empty. For test purposes i created this test function:
(defun test (list)
(if (null (caddr list))
(make-node 1)
(caddr list)))
if uses the make-node function defined as:
(defun make-node (atm)
(cons atm `(`() `())))
when running (make-node 6) I get:
(6 (QUOTE NIL) (QUOTE NIL))
which is what I want.
i then call (test (make-node 6)) which i then get:
(QUOTE NIL)
which is the (caddr list) from test. if you run (null (QUOTE NIL)) you get T which is what i want to get but when i run it from the given test function i receive NIL.
So my question is why when i check if this is null why do i get NIL instead of T?
When you evaluate (null (quote nil)), (quote nil) is evaluated, resulting in nil being used as the argument for the function null.
However when you evaluate something like (null (function-returning-quote-nil)), function-returning-quote-nil is evaluated, resulting in the list (quote nil) which is then used as the argument for the function null without further evaluation.
Compare to the difference between
(null (quote nil)) ; => t
and
(null '(quote nil)) ; => nil
(CADDR '(6 (QUOTE NIL) (QUOTE NIL))) ; ==> (QUOTE NIL) or just 'NIL
The list with the two symbols QUOTE and NIL are not equal to NIL. Only NIL is equal to NIL. eg.
(DEFPARAMETER TEST 'NIL)
TEST ; ==> NIL
(NULL TEST) ; ==> T
This works since 'NIL gets evaluated to NIL and assigned to TEST. TEST gets evaluated to NIL and it's CLs NULL value. However:
(DEFPARAMETER TEST2 ''NIL)
TEST2 ; ==> 'NIL or (QUOTE NIL)
(NULL TEST2) ; ==> NIL
A list with two elements QUOTE and NIL, famously displayed as 'NIL, is NOT NIL. Only NIL is NIL.
EDIT
After looking at your comments about unquoting I'm pretty sure you want this as make-node:
(defun make-node (atm)
(cons atm '(() ())))
(test (make-node 6)) ; ==> (1 NIL NIL)
There is no such thing as unquoting in a data structure and unless you actually want the symbol quote in your data there is no sense in having quotes inside something quoted. (Half truth since there is, but it involves macros)

Lisp: Why and how does '(nil nil) evaluate to true?

(if '(nil nil)
'print-true
'print-false)
(if '(nil)
'print-true
'print-false)
In the code above, why does the Lisp interpreter always evaluate these forms to true (print-true). I thought nil represented false in Common Lisp.
I am using GNU CLISP.
nil is false. Anything else is true. '(nil) is a list with one element, namely nil. '(nil nil) is a list with two elements, namely nil and nil. Neither of these expressions is the same as nil by itself, so if sees it as true.
nil is equivalent to an empty list.
CL-USER> (if (list ) 'print-true 'print-false)
; prints PRINT-FALSE
CL-USER> (if (list nil) 'print-true 'print-false)
; prints PRINT-TRUE
'(nil) is equiv to (list nil) which is different from an empty list.

Stripping duplicate elements in a list of strings in elisp

Given a list such as
(list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
how would I build a new list with the duplicate strings removed, as well as the nils stripped, i.e.
(list "foo" "bar" "moo" "affe")
The order of the elements needs to be preserved - the first occurence of a string may not be removed.
The lists I'm dealing with here are short, so there's no need to use anything like a hash table for the uniqueness check, although doing so certainly wouldn't hurt either. However, using cl functionality is not a viable option.
Try "Sets and Lists" in the "Lists" section of the Emacs Lisp Reference Manual:
(delq nil (delete-dups (list "foo" "bar" nil "moo" "bar" "moo" nil "affe")))
The Common Lisp package contains many list manipulation functions, in particular remove-duplicates.
(require 'cl)
(remove-duplicates (list "foo" "bar" nil "moo" "bar" "moo" nil "affe")
:test (lambda (x y) (or (null y) (equal x y)))
:from-end t)
Yes, I realize you said you didn't want to use cl. But I'm still mentioning this as the right way to do it for other people who might read this thread.
(Why is cl not viable for you anyway? It's been shipped with Emacs for about 20 years now, not counting less featured past incarnations.)
If you use dash.el library, that's all you need:
(-distinct (-non-nil '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
dash.el is written by Magnar Sveen and it's a great list manipulation library with many functions for all kinds of tasks. I recommend to install it if you write lots of Elisp code. Function -distinct removes duplicate elements in a list, -non-nil removes nil elements. While the above code is sufficient, below I describe an alternative approache, so feel free to ignore the rest of the post.
-non-nil was added in version 2.9, so if for some reason you have to use earlier versions, another way to achieve the same is to use -keep with built-in identity function, which just returns whatever it is given: (identity 1) ; => 1. The idea is that -keep keeps only elements, for which the predicate returns true (“non-nil” in Lisp jargon). identity obviously returns non-nil only for whatever values that are not nil:
(-distinct (-keep 'identity '(1 1 nil 2 2 nil 3)) ; => (1 2 3)
This is a short example:
(delete-duplicates '("~/.emacs.d" "~/.emacs.d") :test #'string-equal) ;; '("~/emacs.d")
Basically you use the :test keyword to select the function string-equal to test if the elements are duplicated.
Else the default function test doesn't check string equality.
Here ya go:
(defun strip-duplicates (list)
(let ((new-list nil))
(while list
(when (and (car list) (not (member (car list) new-list)))
(setq new-list (cons (car list) new-list)))
(setq list (cdr list)))
(nreverse new-list)))