checking if list is all numbers in lisp - lisp

so I have a program:
(defun add (L)
(cond((endp L) nil)
(t(cons(1+(first L)))(add(rest L)))))
that will add 1 to each member of the list. I want to check if the list is all numbers and return nil if not, and don't know how to go about doing that within the defun.
I thought of doing
(defun add (L)
(cond((endp L) nil)
((not(numberp(first L))) nil)
(t(cons(1+(first L)))(add(rest L)))))
but that will still return the beginning of the list if the non number is in the middle. How would I pre check and return nil at the beginning?

You can wrap it in a condition-case
(defun add (L)
(condition-case nil
(mapcar '1+ L)
(error nil)))

Another possibility is to use iteration:
(defun add (l)
(loop for x in l
if (numberp x)
collect (1+ x)
else do (return-from add nil)))
The function is immediately exited with nil on the first non numeric element.

You would not implement iteration using recursion, since Lisp already provides iteration constructs. Example: MAPCAR.
Common Lisp also provides control flow constructs like RETURN-FROM, where you return from a block. A function defined by DEFUN has a block with its name and BLOCK can also create a named block explicitly. Examples for both:
CL-USER 62 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 nil 5 6)))
NIL
CL-USER 63 > (block mapping
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from mapping nil)))
'(1 2 3 4 5 6)))
(2 3 4 5 6 7)
As function:
CL-USER 64 > (defun increment-list (list)
(mapcar (lambda (item)
(if (numberp item)
(1+ item)
(return-from increment-list nil)))
list))
INCREMENT-LIST
CL-USER 65 > (increment-list '(1 2 3 4 5 6))
(2 3 4 5 6 7)
CL-USER 66 > (increment-list '(1 2 3 nil 5 6))
NIL

I'd say that an idiomatic way, in Common Lisp, of checking that all elements in a list are numbers would be (every #'numberp the-list), so I would probably write this as:
(defun add-1 (list)
(when (every #'numberp list)
(mapcar #'1+ list)))
It would be possible to use (if ...) or (and ...), but in this case I would argue that (when ...) makes for the clearest code.

The difficulty is that propagating nil results in the nil at the end of the list causing everything to be nil. One solution is to check that add returns nil but (rest xs) is not nil. However, IMO it is more straightforward to just iterate over the list twice, checking for numbers the first time and then doing the addition on the second iteration.
Try this:
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (let ((r (add (rest xs))))
(cond ((and (not r) (rest xs)) nil)
(t (cons (1+ (first xs)) r)))))))
Barring mistakes on my end, this results in:
(add '()) => nil
(add '(1 2)) => '(2 3)
(add '(x y)) => nil
(add '(1 2 y)) => nil
EDIT: Without let. This results in 2^(n+1)-1 calls to add for a list of length n.
(defun add (xs)
(cond ((endp xs) nil)
((not (numberp (car xs))) nil)
(t (cond ((and (not (add (rest xs))) (rest xs)) nil)
(t (cons (1+ (first xs)) (add (rest xs)))))))))

Related

Undefined function b in Lisp

I am attempting to write a function that calls a list recursively and reverses its order. However I need to make the function operate every other recursive level and I am attempting to pass boolean arguments to use as a flag. I am very new to Lisp and keep getting an Undefined function B error.
(defun revList (L b)
(cond ((null L) nil)
((b T)
(append (revList (cdr L nil))
(list (car L))))
((b nil)
(append (revList (cdr L T))
(list (car L))))))
(print (revlist '(1 (2 3) (4 (5 6)) (7 (8 (9 10)))) t))
The first problem, and the reason for the reported error message Undefined function B is that some test forms in the cond form are attempting to call a function b which has not been defined. In a cond form the test forms are evaluated, and the result is used to determine which branch should be used. When (b T) or (b nil) are evaluated, it is expected that b is a function or macro. Instead you should use an expression which evaluates to either a true value or nil here.
There is another problem of misplaced parentheses around a couple of calls to cdr: (cdr L nil) and (cdr L T).
Once these problems are fixed, the code looks like this:
(defun revList (L b)
(cond ((null L) nil)
(b
(append (revList (cdr L) nil)
(list (car L))))
(t
(append (revList (cdr L) t)
(list (car L))))))
I'm going to rewrite the above function using some better names to make things a bit more clear. Note that the idiomatic way to introduce an else clause into a cond form is to use t as the test form in the final clause:
(defun rev-helper-1 (xs reverse-p)
(cond ((null xs) nil)
(reverse-p
(append (rev-helper-1 (cdr xs) nil)
(list (car xs))))
(t
(append (rev-helper-1 (cdr xs) t)
(list (car xs))))))
This code compiles and runs, but probably does not do what is expected. When reverse-p is true the code does exactly the same thing as when it is false, except that the sense of reverse-p is flipped. So the code always reverses its input:
CL-USER> (rev-helper-1 '(1 2 3 4) t)
(4 3 2 1)
CL-USER> (rev-helper-1 '(1 2 3 4) nil)
(4 3 2 1)
Further, this code does not descend into nested lists:
CL-USER> (rev-helper-1 '(1 2 3 4 (a b c d (5 6 7 8))) nil)
((A B C D (5 6 7 8)) 4 3 2 1)
It isn't entirely clear from the OP post whether the desired goal is to reverse list elements on alternate recursive calls, or to reverse list elements in alternate levels of nesting. I suspect that the second goal is the correct one.
Reversing on Alternate Recursive Calls
To reverse list elements on alternating recursive calls, the code needs to cons the first element of the list back onto the front of the "reversed" remainder of the list whenever it is in a non-reversing call. In this way, every other element will be moved to the back of the list, and those moved to the back will be in reverse order in the final list.
(defun rev-helper-2 (xs reverse-p)
(cond ((null xs) nil)
(reverse-p
(append (rev-helper-2 (cdr xs) nil)
(list (car xs))))
(t
(cons (car xs)
(rev-helper-2 (cdr xs) t)))))
CL-USER> (rev-helper-2 '(1 2 3 4) t)
(2 4 3 1)
Reversing in Alternate Levels of Nesting
To reverse in alternate levels of nesting, the code needs distinguish between atoms and lists in the input.
If the first element of a list is an atom, and if the current level is a reversing level, then the first element is wrapped in a list and appended to the result of reversing the rest of the level. Otherwise, if the first element is an atom, and the current level is not a reversing level, then the first element is consed onto the front of "reversing" the rest of the level. In this second case "reversing" the rest of the level will not change the ordering of elements at this level, because reverse-p will be false for non-reversing levels; but the code still needs to walk over the list to see if any elements at this level are lists which require further processing.
Otherwise, the first element is a list. If the current level is a reversing level, then the first element must be "reversed", i.e., processed by the reversing function, then wrapped in a list and appended to the end of reversing the rest of the list. Otherwise the current level is not a reversing level, so the first element must be processed by the reversing function and consed onto the front of "reversing" the rest of the list.
(defun rev-helper-3 (xs reverse-p)
(cond ((null xs) nil)
((atom (car xs))
(if reverse-p
(append (rev-helper-3 (cdr xs) t)
(list (car xs)))
(cons (car xs)
(rev-helper-3 (cdr xs) nil))))
(reverse-p
(append (rev-helper-3 (cdr xs) t)
(list (rev-helper-3 (car xs) nil))))
(t
(cons (rev-helper-3 (car xs) t)
(rev-helper-3 (cdr xs) nil)))))
Using a let form to bind the results of (car xs) and (cdr xs) to a couple of descriptive identifiers reduces the number of calls to car and cdr and makes this a bit easier to read:
(defun rev-helper-4 (xs reverse-p)
(if (null xs) nil
(let ((first (car xs))
(rest (cdr xs)))
(cond ((atom first)
(if reverse-p
(append (rev-helper-4 rest t)
(list first))
(cons first
(rev-helper-4 rest nil))))
(reverse-p
(append (rev-helper-4 rest t)
(list (rev-helper-4 first nil))))
(t
(cons (rev-helper-4 first t)
(rev-helper-4 rest nil)))))))
Let's write a convenience function to make it nicer to call rev-helper-4:
(defun rev-alt (xss)
(rev-helper-4 xss t))
CL-USER> (rev-alt '(1 2 3 4))
(4 3 2 1)
CL-USER> (rev-alt '(1 2 3 4 (a b c d)))
((A B C D) 4 3 2 1)
CL-USER> (rev-alt '(1 2 3 4 (a b c d (5 6 7 8))))
((A B C D (8 7 6 5)) 4 3 2 1)
CL-USER> (rev-alt '(1 (2 3) (4 (5 6)) (7 (8 (9 10)))))
((7 ((9 10) 8)) (4 (6 5)) (2 3) 1)

Check for proper list in Common Lisp

Is there a standard function in Common Lisp that can check against improper lists (i.e. circular and dotted lists) without signaling an error? list-length can check against circular lists (it returns nil for them), but signals type-error when given a dotted list.
Scheme's list? traverses the whole list to make sure it is not dotted or circular; Common Lisp's listp only checks that it's given nil or a cons cell.
Here's the simplest I could come up with:
(defun proper-list-p (x)
(not (null (handler-case (list-length x) (type-error () nil)))))
Since several implementations have been suggested and many unexpected problems have been found, here's a test suite for aspiring proper-list-p writers:
(defun circular (xs)
(let ((xs (copy-list xs)))
(setf (cdr (last xs)) xs)
xs))
(assert (eql t (proper-list-p '())))
(assert (eql t (proper-list-p '(1))))
(assert (eql t (proper-list-p '(1 2))))
(assert (eql t (proper-list-p '(1 2 3))))
(assert (not (proper-list-p 1)))
(assert (not (proper-list-p '(1 . 2))))
(assert (not (proper-list-p '(1 2 . 3))))
(assert (not (proper-list-p '(1 2 3 . 4))))
(assert (not (proper-list-p (circular '(1)))))
(assert (not (proper-list-p (circular '(1 2)))))
(assert (not (proper-list-p (circular '(1 2 3)))))
(assert (not (proper-list-p (list* 1 (circular '(2))))))
(assert (not (proper-list-p (list* 1 2 (circular '(3 4))))))
There is no standard function to do this, perhaps because such a function was seen as rather expensive if it was to be correct, but, really, this just seems like am omission from the language to me.
A minimal (not very performant) implementation, which does not rely on handling errors (Python people think that's a reasonable way to program, I don't, although this is a stylistic choice), is, I think
(defun proper-list-p (l)
(typecase l
(null t)
(cons
(loop for tail = l then (cdr tail)
for seen = (list tail) then (push tail seen)
do (cond ((null tail)
(return t))
((not (consp tail))
(return nil))
((member tail (rest seen))
(return nil)))))))
This takes time quadratic in the length of l, and conses proportional to the length of l. You can obviously do better using an hashtable for the occurs check, and you can use a tortoise-&-hare algorithm do avoid the occurs check (but I'm not sure what the complexity of that is off the top of my head).
I am sure there are much better functions than this in libraries. In particular Alexandria has one.
While thinking about this question, I also wrote this function:
(defun classify-list (l)
"Classify a possible list, returning four values.
The first value is a symbol which is
- NULL if the list is empty;
- LIST if the list is a proper list;
- CYCLIC-LIST if it contains a cycle;
- IMPROPER-LIST if it does not end with nil;
- NIL if it is not a list.
The second value is the total number of conses in the list (following
CDRs only). It will be 0 for an empty list or non-list.
The third value is the cons at which the cycle in the list begins, or
NIL if there is no cycle or the list isn't a list.
The fourth value is the number if conses in the cycle, or 0 if there is no cycle.
Note that you can deduce the length of the leading element of the list
by subtracting the total number of conses from the number of conses in
the cycle: you can then use NTHCDR to pull out the cycle."
;; This is written as a tail recursion, I know people don't like
;; that in CL, but I wrote it for me.
(typecase l
(null (values 'null 0 nil 0 0))
(cons
(let ((table (make-hash-table)))
(labels ((walk (tail previous-tail n)
(typecase tail
(null
(values 'list n nil 0))
(cons
(let ((m (gethash tail table nil)))
(if m
(values 'cyclic-list n tail (- n m))
(progn
(setf (gethash tail table) n)
(walk (cdr tail) tail (1+ n))))))
(t
(values 'improper-list n previous-tail 0)))))
(walk l nil 0))))
(t (values nil 0 nil 0))))
This can be used to get a bunch of information about a list: how long it is, if it is proper, if not if it's cyclic, and where the cycle is. Beware that in the cases of cyclic lists this will return circular structure as its third value. I believe that you need to use an occurs check to do this – tortoise & hare will tell you if a list is cyclic, but not where the cycle starts.
in addition, something slightly less verbose, than the accepted answer:
(defun improper-tail (ls)
(do ((x ls (cdr x))
(visited nil (cons x visited)))
((or (not (consp x)) (member x visited)) x)))
(defun proper-list-p (ls)
(null (improper-tail ls)))
or just like this:
(defun proper-list-p (ls)
(do ((x ls (cdr x))
(visited nil (cons x visited)))
((or (not (consp x)) (member x visited)) (null x))))
seen to pass all the op's test assertions
After our hopeless attempts with tailp, here, sth which uses the
sharp-representation of circular lists :) .
With regex (to detect circular sublist)
(setf *print-circle* t)
(ql:quickload :cl-ppcre)
(defun proper-listp (lst)
(or (null lst) ; either a `'()` or:
(and (consp lst) ; a cons
(not (cl-ppcre::scan "#\d+=(" (princ-to-string lst)))) ; not circular
(null (cdr (last lst)))))) ; not a dotted list
Without regex (cannot detect circular sublists)
(defun proper-listp (lst)
(or (null lst) ; either a `'()` or:
(and (consp lst) ; a cons
(not (string= "#" (subseq (princ-to-string lst) 0 1))) ; not circular
(null (cdr (last lst)))))) ; not a dotted list
(tailp l (cdr l)) is t for circular lists but nil for non-circular lists.
Credits to #tfp and #RainerJoswig who taught me this here .
So, your function would be:
(defun proper-listp (lst)
(or (null lst) ; either a `'()` or:
(and (consp lst) ; a cons
(not (tailp lst (cdr lst))) ; not circular
(null (cdr (last lst)))))) ; not a dotted list
By the way, I use proper-listp by purpose. Correct would be - by convetion proper-list-p. However, this name is already occupied in the CLISP implementation by SYSTEM::%PROPER-LIST-Pwhy the definition of the function raises a continuable error.
Conclusion of our discussion in the comment section:
The behavior of tailp for circular lists is undefined. Therefore this answer is wrong! Thank you #Lassi for figuring this out!

Two common elements between lists

I have a problem with this function two-similar-p.
(defun two-similar-p (list1 list2)
(mapcar
(lambda (e)
(mapcar
(lambda (e1)
(if (equal e e1) t))
list2))
list1))
But is not correct use mapcar because this function returns a new list with T or NIL, but I need only to return a true or false.
ex.
(two-similar-p '(2 1 3) '(1 2 3))
==> ((NIL T NIL) (T NIL NIL) (NIL NIL T))
I was thinking to use recursion to compare the various elements, but I have no idea how to do that.
My function needs to work like:
(two-similar-p '(1 2 3) '(1 4 5)) ; ==> nil
(two-similar-p '(1 2 5) '(1 4 5)) ; ==> t
(two-similar-p '(1 2 6) '(6 4 2)) ; ==> t
Any advice?
The easiest "off-the-shelf" solution is to check that the intersection contains at least two elements:
(defun two-similar-p (l1 l2)
(consp (cdr (intersection l1 l2 :test #'equal))))
A slightly less OTS solution is to use hash tables:
(defun two-similar-p (l1 l2)
(let ((h1 (make-hash-table :test 'equal))
(common 0))
(dolist (x l1)
(setf (gethash x h1) t))
(dolist (x l2)
(when (gethash x h1)
(incf common))
(when (>= common 2)
(return t)))))
The advantage of the second approach is that its complexity is O(len(l1) + len(l2)),
while the mapcar approach will be O(len(l1) * len(l2)).
The standard does not specify the complexity of intersection and friends, but most implementations take good care of their users here (IOW, the complexity will be linear, not quadratic).

Reverse a list with dolist in LISP

I try to reverse a list, i can't use the function "nreverse"
I try :
(defun dolist-reverse (l)
(let ((new-list (make-list (length l))))
(dolist (x l new-list)
(setf new-list (cons x new-list)))))
But the result is :
CL-USER> (dolist-reverse '(1 2 3))
(3 2 1 NIL NIL NIL)
How can i do ? (i need to use dolist)
EDIT :
Finally fix my problem :
(defun dolist-reverse (l)
(let ((new-list))
(dolist (x l new-list)
(setf new-list (cons x new-list)))))
CL-USER 11 > (defun dolist-reverse (list &aux (reverse-list nil))
(dolist (element list reverse-list)
(push element reverse-list)))
DOLIST-REVERSE
CL-USER 12 > (dolist-reverse '(1 2 3))
(3 2 1)
This one makes same thing, without changing argument to the procedure;
(defun my-reverse (l)
(if (null l) nil
(append
(my-reverse (cdr l))
(list (car l)))))

lisp apply append

i worte this function to remove numbers from a list x
(defun rm-nums (x)
(cond
((null x) nil)
(t (mapcar 'numberp x))))
however when i enter (rm-nums '(32 A T 4 3 E))
returns (T NIL NIL T T NIL)
i want it instead of returning T or Nil, i want it to return the values that caused NIL only [which are not numbers]
so this example should return (A T E)
i am supposed to use mapcar WITHOUT recursion or iteration or the bultin function "remove-if"
i think it is related to something called apply-append but i know nothing about it. any help?
I think your course had this in mind:
(defun my-remove-if (pred lst)
(apply #'append (mapcar (lambda (x)
(and (not (funcall pred x))
(list x)))
lst)))
It does use apply and append and mapcar, like you said. Example usage:
(my-remove-if #'numberp '(32 a t 4 3 e))
=> (a t e)
More idiomatic solution suggested by Rörd:
(defun my-remove-if (pred lst)
(mapcan (lambda (x)
(and (not (funcall pred x))
(list x)))
lst))