List recursion base case - lisp

(cond ((null list) nil) ;This is true if we are not at the end of the list?
while
(cond ((null lst) '()) ; this means we are at the empty set?
Not quite sure how these are different, can anyone help?
Thanks a lot

They aren't different. nil and '() denote exactly the same object in Lisp:
[1]> (eq nil '())
T
Some people will tell you to use nil to denote the boolean false, and '() or () for the empty list. That's just a matter of coding style, though.

Related

LISP better understanding of multilevel lists

I am trying to gain a better understanding of multilevel lists in lisp by making a function in which I delete all the elements that are not numbers from a multilevel list. I first try to flatten it with striv0 function and then check if the first argument of the list is numerical or not. However I have a problem when trying the function
(func '(5 (5 2 (8)(7 (9)5))))
. I get :COND :variable IF HAS NO VALUE
The code :
(DEFUN striv0 (lis)
(COND ((NULL lis) NIL)
((ATOM lis) (LIST lis))
(T (APPEND (striv0 (FIRST lis))
(striv0 (REST lis))))
))
(DEFUN func (lis)
(LET( (newList (striv0 lis)) ))
(COND ((NULL newList) NIL)
( T(IF (NUMBERP (FIRST newList))
((func(REST newList)))))))
I believe I have managed to solve the problem by molding the second function into the first by checking for numerical arguments or inner lists if it's neither one it moves further along the list.:
(DEFUN checkNumber (lis)
(COND ((NULL lis) NIL)
((ATOM lis) (LIST lis))
(T (if ( or(NUMBERP ( FIRST lis))(LISTP (FIRST lis)))
(APPEND ( checkNumber (FIRST lis))
( checkNumber (REST lis)))
( checkNumber (REST lis)) )
)
)
)
Here some line-by-line feedback and some hints:
(DEFUN func (lis) ; why is this called FUNC
; and not something useful?
; why is the variable called
; LIS and not LIST?
(LET( (newList (striv0 lis)) )) ; why is this not indented?
; why does LET not have
; body forms?
; why is the LET ending here?
(COND ((NULL newList) NIL) ; why is this not indented?
( T(IF (NUMBERP (FIRST newList)) ; why is this not indented?
((func(REST newList))))))) ; why are there so
; many parentheses?
; why is it starting
; with two parentheses?
First, format your code. The accepted convention is to use lower-case symbols and separate word parts within the symbol names with dashes, e. g. new-list. Indentation is used to align forms of the same level at the same text column. There are various write-ups of Lisp style, here is one. Here is how your code would look then:
(defun striv0 (lis)
(cond ((null lis) nil)
((atom lis) (list lis))
(t (append (striv0 (first lis))
(striv0 (rest lis))))))
(defun func (lis)
(let ((new-list (striv0 lis))))
(cond ((null new-list) nil)
(t (if (numberp (first new-list))
(cons (first new-list) (func (rest new-list)))))))
A good editor will do the indentation for you. If the indentation then does not match your expectation, you know that you made a syntax mistake. The editor will also show matching parenthesis pairs.
Let takes as first argument a list of bindings and then any number of forms in its body. Only within that body are the bindings in effect. You want to put your cond form into that body:
(defun func (lis)
(let ((new-list (striv0 lis)))
(cond ((null new-list) nil)
(t (if (numberp (first new-list))
((func (rest new-list))))))))
Note how the indentation automatically reflects the code structure: the cond form is now indented two spaces to show that it is inside the let body. What I actually edited is to move the closing parenthesis of the let form to the end.
That last form ((func (rest new-list))) is not a valid Lisp form there. A form must always start with an operator (which can either be a symbol or a lambda form). I think that you had something that looked right in an earlier version of your question: (cons (first new-list) (func (rest new-list))).
I'd now try to find better names for those functions. Your striv0 might conventionally be named flatten. “Multilevel lists” are usually called “trees” in Lisp. Your func might thus be called keep-numbers-from-tree.
I'm not sure whether the flattening is part of your requirements. In any case, I'd keep this separate, since it seem superfluous to do this again each time through the recursion. First flatten, then filter numbers.
If flattening is not part of your requirements, don't do it. When going through the tree, there are only three possibilities at each point: it is a list (then recurse), it is a number (keep), or it is a non-numeric atom (skip).

Checking circularity in lisp - same variable through recursive function

I'm trying to create a function that would test whether the given list is circular with a re-starting point being the beginning of the list.
Expected results:
(setq liste '(a b c))
(rplacd (cddr liste) liste)
(circular liste) => t
(circular '(a b c a b c)) => nil
As I simply want to test if any subsequent item is 'eq' to the first one, I don't want to build the whole tortoise and hare algorithm.
Here is my code :
(defun circular (liste)
(let (beginningliste (car liste)))
(labels ( (circ2 (liste)
(cond
((atom liste) nil)
((eq (car liste) beginningliste) t)
(t (circ2 (cdr liste)))
) ) ) ) )
It doesn't give the expected result but I don't understand where my error is
I'm not sure I'm using 'labels' correctly
Is there a way to do that without using 'labels'?
Edit. I guess I have answered my third question as I think I have found a simpler way. Would this work?
(defun circular (liste)
(cond
((atom liste) nil)
((eq (car liste) (cadr liste)) t)
(t (circular (rplacd liste (cddr liste))))
)
)
First, the behavior is undefined when you mutate constant data: when you quote something (here the list), the Lisp environment has the right to treat it as a constant. See also this question for why defparameter or defvar is preferred over setq. And so...
(setq list '(a b c))
(rplacd (cddr list) list)
... would be better written as:
(defparameter *list* (copy-list '(a b c)))
(setf (cdr (last *list*)) *list*)
Second, your code is badly formatted and has bad naming conventions (please use dashes to separate words); here it is with a conventional layout, with the help of emacs:
(defun circularp (list)
(let (first (car list)))
(labels ((circ2 (list)
(cond
((atom list) nil)
((eq (car list) first) t)
(t (circ2 (cdr list))))))))
With that formatting, two things should be apparent:
The let contains no body forms: you define local variables and never use them; you could as well delete the let line.
Furthermore, the let is missing one pair of parenthesis: what you wrote defines a variable name first and another one named car, bound to list. I presume you want to define first as (car list).
You define a local circ2 function but never use it. I would expect the circularp function (the -p is for "predicate", like numberp, stringp) to call (circ2 (cdr list)). I prefer renaming circ2 as visit (or recurse), because it means something.
With the above corrections, that would be:
(defun circularp (list)
(let ((first (car list)))
(labels ((visit (list)
(cond
((atom list) nil)
((eq (car list) first) t)
(t (visit (cdr list))))))
(visit (cdr list)))))
However, if your list is not circular but contains the same element multiple times (like '(a a b)), you will report it as circular, because you inspect the data it holds instead of the structure only. Don't look into the CAR here:
(defun circularp (list)
(let ((first list))
(labels ((visit (list)
(cond
((atom list) nil)
((eq list first) t)
(t (visit (cdr list))))))
(visit (cdr list)))))
Also, the inner function is tail recursive but there is no guarantee that a Common Lisp implementation automatically eliminates tail calls (you should check with your implementation; most can do it on request). That means you risk allocating as many call stack frames as you have elements in the list, which is bad. Better use a loop directly:
(defun circularp (list)
(loop
for cursor on (cdr list)
while (consp cursor)
thereis (eq cursor list)))
Last, but not least: your approach is a very common one but fails when the list is not one big circular chain of cells, but merely contains a loop somewhere. Consider for example:
CL-USER> *list*
#1=(A B C . #1#)
CL-USER> (push 10 *list*)
(10 . #1=(A B C . #1#))
CL-USER> (push 20 *list*)
(20 10 . #1=(A B C . #1#))
(see that answer where I explain what #1= and #1# mean)
The lists with numbers in front exhibit circularity but you can't just use the first cons cell as a marker, because you will be looping forever inside the sublist that is circular. This is the kind or problems the Tortoise and Hare algorithm solves (there might be other techniques, the most common being storing visited elements in a hash table).
After your last edit, here is what I would do if I wanted to check for circularity, in a recursive fashion, without labels:
(defun circularp (list &optional seen)
(and (consp list)
(or (if (member list seen) t nil)
(circularp (cdr list) (cons list seen)))))
We keep track of all the visited cons cells in seen, which is optional and initialized to NIL (you could pass another value, but that can be seen as a feature).
Then, we say that a list is circular with respect to seen if it is a cons cell which either: (i) already exists in seen, or (ii) is such that its CDR is circular with respect to (cons list seen).
The only additional trick here is to ensure the result is a boolean, and not the return value of member (which is the sublist where the element being searched for is the first element): if your environment has *PRINT-CIRCLE* set to NIL and the list is actually circular, you don't want it to try printing the result.
Instead of (if (member list seen) t nil), you could also use:
(when (member list seen))
(position list seen)
and of course (not (not (member list seen)))

Check the presence of an item in lisp

To complete an exercise, I need to check if an element is in a list or not. I know that there is the function member in lisp, but our instructor is very strict and doesn't let us use things that haven't yet been covered in the course.
What would be a way to check if an atom is in a list by using only cond, nil, car, not, cdr, +, equal, defun?
Edit:
After Doseke's comment; here is an attempt:
(defun presence (list item)
(cond
((atom list) nil)
((equal (car list) item) t)
((consp list) (presence (cdr list) item))
(t nil)
)
)
edit: I changed the title to make it match with my actual question
Since you are limited in used features, it could be something like this, i guess:
(defun member-2 (x xs)
(cond ((not xs) nil)
((equal x (car xs)) xs)
(t (member-2 x (cdr xs)))))

Check if a list contains at least one non-nil element

The title pretty much tells everything.
I am searching for something like
(atleastonenonnil '(nil nil nil nil '(A B C)))
=> T
I could do it in a recursive way, but I couldn't. Should I use some built-in function?
I'm using cLisp
If you deal with the first element of the list then all the rest can be done recursively. The code is this:
(defun at-least-one-nonnil (l)
(and (not (nullp l))
(or (car l)
(at-least-one-nonnil (cdr l))))))
Of course in this simple case there is already a built-in function.
(defun at-least-one-nonnil-v2 (l)
(some #'identity l))
but that doesn't help you learn about recursion.
Works for me.( AutoCAD's AutoLisp) Example:
(repeat 100000 (setq longlist (cons nil longlist)))
then
(setq longlist (append longlist (list 1)))
this is a 100001 element list with only 1 non-nil element at the end.
(apply 'or longlist)
returns T. Isn't this the right answer or the list isn't long enough?
what about:
(apply 'or '( your list here )) ;; ?

How does Lisp "prog" work in this example?

I'm a beginner in lisp and I need somebody to explain to me how the prog form works, step by step. What is the initial value of l1 ? Nil ?
The problem outputs T if the list has an even number of elements on the first level, nil if not.
(defun nr_par (l)
(prog ((l1 l))
ciclu
(cond
((null l1) (return T))
((null (cdr l1)) (return NIL))
((null (cddr l1)) (return T))
(T (setf l1 (cddr l1))
(go ciclu)))))
On console:
(nr_par '(1 2 3 4 5 6 7 8))
T
The program is straightforward, but not very idiomatic lisp (it is rather imperative instead of functional). Step by step goes as follows.
prog uses a series of variable bindings, in this case, l1 is assigned the value of l initially. Then, a series of statements in which a loop starts (again, not very lisp idiomatic).
This type of loops use a tag (ciclu) and a goto instruction (go), again, not recommended, but it is there. After that, the cond checks a series of cases. When the list is empty (null), you return true, in other cases, you check if the length is even or odd, and return the value in consequence.
In the case that the list is longer than one or two elements (neither of the cases is null), the l1 list is adjusted to point to the next of the next element of itself (the cddr function).
Finally, the go function turns the program back to the ciclu tag.
The program will finish when any of the cond clauses is met, returning either T or NIL.
See PROG in CLHS: L1 is var, L is init-form, so the initial value of L1 is the value of L.
As the CLHS page for prog says, it does three things: lets you have local vars and initialize them; lets you have tags as in tagbody and use go; and lets you use return as inside a block named NIL:
(defun nr_par (l)
(prog ((l1 l)) ; local binding(s)
ciclu
(if (null l1) (return T)) ; return
(if (null (cdr l1)) (return NIL))
(setf l1 (cddr l1))
(go ciclu))) ; go
(defun nr_par1 (l) ; directly equivalent
(labels ((ciclu (l1)
(if (null l1) (return-from ciclu T))
(if (null (cdr l1)) (return-from ciclu NIL))
(ciclu (cddr l1))))
(ciclu l)))
(defun nr_par2 (l) ; also equivalent
(do ((l1 l (cddr l1)))
(NIL) ; while T ...
(cond
((null l1) (return T))
((null (cdr l1)) (return NIL)))))
Function call is a glorified goto after all, isn't it?
See also Longest decreasing sequence in Lisp for an example representing several mutually-recursive functions hand-compiled into a prog with a bunch of GO statements.