Unbound Variable error in Lisp - lisp

I am trying to do a function that removes duplicates from a list using Common Lisp on LispWorks.
So I did two functions. The first one "remove-e" removes an element from a list and a second one "remove-rep" uses the first one to return a list without duplicates.
Here is my code for the first one:
(defun remove-e (L e)
(if (null L)
L
(if (= e (car L))
(remove-e (cdr L) e)
(cons (car L) (remove-e (cdr L) e)))))
It works good when given a list of numbers but when I give it letters, I get this error:
(remove-e '(a a b a d a g a h t) a)
Error: The variable A is unbound.
For my second function:
(defun remove-rep (l)   
(if (null l)
l
(cons (car l)
(remove-rep (remove-e (cdr l) (car l))))))
This is the error message that I get when trying to test it:
CL-USER 12 : 6 > (remove-rep '(1 2 3 1 5 1 1))
Error: The variable   is unbound.
I saw that there are some similar questions, but couldn't find the common points of my program with these:
Unbound variable in Lisp ,
Unbound variable in Common Lisp

remove-e only works with a list of numbers, because you're using = to compare elements. If you want to be able to work with symbols as well, use eql:
(defun remove-e (L e)
(if (null L) L
(if (eql e (car L)) (remove-e (cdr L) e)
(cons (car L) (remove-e (cdr L) e)))))
Then when you call it, you have to quote the symbol argument, to prevent it from being evaluated as a variable.
(remove-e '(a a b a d a g a h t) 'a)
The problem in remove-rep is that you somehow typed some non-printing, multi-byte characters at the end of the first line. It works correctly with those characters removed. Try retyping the function, or just copy/paste this:
(defun remove-rep (l)
(if (null l) l
(cons (car l) (remove-rep (remove-e (cdr l) (car l))))))
BTW, Lisp programmers don't generally put ) on new lines like you do, they put them at the end of the line like this.

Related

Flattening lists (while removing 'nil' and keeping atoms after " . ") in lisp

I want to create a function that would flatten a list and remove all potential nil inside.
Expected behavior, example 1:
(myfunc '(a (b (c) (d)) (e f) (g (h)) nil)) => (a b c d e f g h)
Expected behavior, example 2:
(myfunc '(a . d)) => (a d)
my function so far:
(defun myfunc (l)
(cond
((atom l) nil)
((and (atom (car l)) (not (equal (car l) nil))) (cons (car l) (myfunc (cdr l))))
(t (append (myfunc (car l)) (myfunc (cdr l))))))
My function works as expected for the first example, but not the second.
I get:
(myfunc '(a . d)) => (a)
Why doesn't it keep that d?
Is there a way to fix it?
Perhaps you should think about what the flatten function should do, in plain English:
Base case: If flattening nil, return an empty list.
Base case: If flattening single atoms, return a list containing just that.
Recursive case: If flattening pairs, return a list appending the flattening of its car with the flattening of its cdr.
Here's how I'd implement the description I just gave:
(defun flatten (x)
(cond ((null x) x)
((atom x) (list x))
(t (nconc (flatten (car x)) (flatten (cdr x))))))

I don't know what this function should do

I have here a function that I need to modify so that I would avoid the double recursive call of (f (car l)) . First of all I can't figure it out what it shows..
If I pass (f '((3 4) 5 6)) it shows me CAR: 3 is not a list
Can anybody help me understand and then modify it?
(DEFUN F (L)
(COND
((NULL L) 0)
((> (f (car l)) 2) (+ (car l) (f (cdr l))))
(T (f (CAR L)))
))
You can figure out what this function should accept as input by looking at what it does with the input, and what it returns by looking at what each case returns. There are three cases:
Case 1
((NULL L) 0)
In this case, L can be nil, and 0, which is a number, is returned.
Case 2
((> (f (car l)) 2) (+ (car l) (f (cdr l))))
In this case, we call both car and cdr on l, so l had better be a cons. We also compare (f (car l)) with 2, so f must return a number, at least for whatever type (car l) is. Since we're calling + with (car l), (car l) must be a number. So f must return a number when given a number. Now, we're also calling + with (f (cdr l)), so whatever type (cdr l) has, f had better return a number for it, too.
Case 3
(T (f (CAR L)))
This doesn't put many constraints on us. This just says that if we didn't have either of the first two cases, then we return (f (car l)). Since checking the second case didn't fail, and because we're calling (car l), l still has to be a cons in this case.
So what is f?
Well, it's still not immediately clear what f is, but we can write it as a piecewise function, and maybe that will help. It take a list, which is either the empty list or a cons that has a first and a rest.
f [] = 0
f x:xs = if (f x) > 2
then x + (f xs)
else (f x)
To modify it so that you only call (f (car l)) is easy enough, although since we know that the input needs to be a list, I'm going to use first and rest to suggest that, rather than car and cdr.
(defun f (list)
(if (endp list)
0
(let ((tmp (f (first list))))
(if (> tmp 2)
(+ (first list)
(f (rest list)))
tmp))))
Let's try to walk through some possible inputs and try to cover the different code branches. What sort of input could we call this with? Well, we can call it with ():
CL-USER> (f '())
0
That takes care of the first then branch. Now what if we want to hit the second? Then we need to pass something that's not the empty list, so it looks like (? . ??). Now the first thing that has to happen is a recursive call to(f (first list)). The only way that this is going to work is if(first list)is also a list that we can pass tofand get a value back. Then(first list)` must have either been the empty list or another suitable list. So we can call:
CL-USER> (f '(() a b c))
0
In general, we can call f with () and with any list such that (first (first (first ... (first list)))) is (). Can we call it with anything else? It doesn't appear so. So now we know what the acceptable inputs to f are:
input ::= ()
| (input . anything)
and the output will always be 0.

Lisp function explanation

I have this example in LISP that removes from every level of a list a given number:
(defun remove_aux (e l)
(cond
((equal e l) nil)
((atom l) (list l))
(t(list(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))))))
(defun remove_el (e l)
(car (remove_aux e l)))
So, if it run like this: (remove_el 2 '(1 2 3 ((2 3 2) 4))) => (1 3 ((3) 4))
What I don't exactly understand is how this line works: (t(list(apply 'append (mapcar #'(lambda (l) (sterge_aux e l)) l))))
If I have the line without list and append ((t(mapcar #'(lambda (l) (remove_aux e l)) l))) the result is ((1) NIL (3) ((NIL (3) NIL) (4)))) if it has append but not list ( (t(apply 'append (mapcar #'(lambda (l) (remove_aux e l)) l))) ) then the result is (1 3 3 4) and I don't get why because I did (apply 'append '((1) NIL (3) ((NIL (3) NIL) (4))))) in the Common Lisp console and the result was ((1 3 (NIL (3) NIL) (4))) so I'm really confused. Can somebody explain to me how this all works step by step?
I've annotated the code below to, I hope, explain what's going on. You're probably getting confused because l is getting redefined within a lambda... so the t line (in your example) has 2 "l"s on it but the first one isn't the same as the second one.
(defun remove_aux (e l)
(cond
((equal e l) nil) ;if e equals l return nil
((atom l) (list l)) ;if l is an atom return a list with just l in it
(t ; otherwise...
(list ;create a list
(apply 'append ; whose contents are created by appending
; together the lists that come out of this mapcar
; (apply the append method)
(mapcar #'(lambda (l) ( ; iterate over each of the elements in list l
; the one after the lambda not the one
; being passed to the lambda.
; (this is a horrible name choice
; lambda(l-item) would be much better)
remove_aux e l
; recursively call this method
; with e (which was passed in at the start)
; and l which isn't the l passed in,
; but is an entry of it (see why naming's
; so important?)
; this returns a list
; which will get appended by the append
; with the results of all the other calls
; to remove_aux for each item in the outer l
)
) l)
)))))
(defun remove_el (e l)
(car (remove_aux e l)
)
)
;; append elements of each list in argument together
(append '(a) '(b) '(c d) '(e)) ; ==> (a b c d e)
;; append elements of each sublist in argument
(apply #'append '((a) (b) (c d) (e))) ; ==> (a b c d e)
;; apply function on each element of list into new list
(mapcar #'(lambda (x) (+ x 1)) '(1 3 5 6)) ; ==> (2 4 6 7)
So what does the default case do in your function.. Well it applies itself to each sublist of lst and wrap it in a list so if l is '(a y 2 z) and e is 2, well then the result from mapcar is '((a) (y) () (z)) which is then the argument to apply-append which connects the elements together into one list again. When connecting the lists the element that was to be removed is an empty list and it's effectively ignored in the concatenation process.
Since all the lists appended you create in the helper, you could replace the apply-append with (mapcan #'(lambda (l) (remove_aux e l)) l). A more obvious way to do this would be using reduce while a more efficient way might use loop.
A procedure that achieve what you want to achieve is essentially like below procedure:
(defun remove-all (e l)"Removes all occurrences of e from a list l."
(cond
((null l) '())
((equal e (car l)) (remove-all e (cdr l)))
((not (atom (car l)))
(cons (remove-all e (car l))
(remove-all e (cdr l))))
(t (cons (car l)
(remove-all e (cdr l))))))
;note: the e is not neccessarily an atom, the l is not necessarily a list of atoms.
The procedure in your question has unnecessarily cluttered pieces, like append, maps etc.
if you recomment below i will explain the algorithm.
have a nice hack.

Learning Lisp. Can't seem to get a value from one function and use it within another

I'm trying to find the maximum number within a list, then do something with it:
(defun maxList (l)
(if (= (length l) 1)
(first l)
(if (> (first l) (maxList (rest l)))
(first l)
(maxList (rest l))
);if
);if
);defun
(defun try-let (l)
(let (a (maxList l))
(print a)
);let
);defun
However it prints null, yet maxList works. What am I doing wrong ?
You're missing a pair of parentheses:
(let ((a (maxList l)))
This is because let takes a list of bindings as in
(let ((a 1) (b 2) (c 'foo))
expr)
so in this case you have to pass a one-element list containing the binding (a (maxList l))
(defun maxList (l)
(if (= (length l) 1)
Calling LENGTH is not a good idea. It traverses the whole list.
(first l)
(if (> (first l) (maxList (rest l)))
(first l)
(maxList (rest l)))))
Above calls MAXLIST twice. Maybe here a LET is useful? How about the function MAX?
If you compile your function, a Common Lisp system will complain.
CL-USER 35 > (defun try-let (l)
(let (a (maxList l))
(print a)))
TRY-LET
CL-USER 36 > (compile 'try-let)
;;;*** Warning in TRY-LET: MAXLIST is bound but not referenced
This shows that the Lisp compiler thinks MAXLIST is a variable. Something is wrong. Next look up the syntax of LET.
See Special Operator LET, LET*
let ({var | (var [init-form])}*) declaration* form* => result*
Which says that it is a list of variables or a list of (variable initform). So you can see that you have missed to make it a list. You have just written one binding.

LISP - removing an element from a list with nested lists

I need to remove an element from a list which contain inner lists inside. The predefined element should be removed from every inner list too.
I have started working with the following code:
(SETQ L2 '(a b ( a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a )) ; defined my list
; Created a function for element removing
(defun elimina (x l &optional l0)
(cond (( null l)(reverse l0))
((eq x (car l))(elimina x (cdr l) l0))
(T (elimina x (cdr l) (cons (car l) l0))))
)
(ELIMINA 'a L2)
But unfortunately it removes only elements outside the nested lists.
I have tried to create an additional function which will remove the element from the inner lists.
(defun elimina-all (x l)
(cond ((LISTP (CAR L))(reverse l)(elimina x (car l)))
(T (elimina-all x (CDR L)))
)
)
but still unsuccessfully.
Can you please help me to work it out?
Thank you in advance.
First of all, I'd suggest you read this book, at least, this page, it explains (and also gives very good examples!) of how to traverse a tree, but most importantly, of how to combine functions to leverage more complex tasks from more simple tasks.
;; Note that this function is very similar to the built-in
;; `remove-if' function. Normally, you won't write this yourself
(defun remove-if-tree (tree predicate)
(cond
((null tree) nil)
((funcall predicate (car tree))
(remove-if-tree (cdr tree) predicate))
((listp (car tree))
(cons (remove-if-tree (car tree) predicate)
(remove-if-tree (cdr tree) predicate)))
(t (cons (car tree)
(remove-if-tree (cdr tree) predicate)))))
;; Note that the case of the symbol names doesn't matter
;; with the default settings of the reader table. I.e. `D' and `d'
;; are the same symbol, both uppercase.
;; Either use \ (backslash) or || (pipes
;; around the symbol name to preserve the case. Eg. \d is the
;; lowercase `d'. Similarly, |d| is a lowercase `d'.
(format t "result: ~s~&"
(remove-if-tree
'(a b (a 2 b) c 1 2 (D b (a s 4 2) c 1 2 a) a)
#'(lambda (x) (or (equal 1 x) (equal x 'a)))))
Here's a short example of one way to approaching the problem. Read the comments.
Maybe like this:
(defun elimina (x l &optional l0)
(cond ((null l) (reverse l0))
((eq x (car l)) (elimina x (cdr l) l0))
(T (elimina x (cdr l) (cons (if (not (atom (car l)))
(elimina x (car l))
(car l))
l0)))))
I was looking for the same answer as you and, unfortunately, I couldn't completely understand the answers above so I just worked on it and finally I got a really simple function in Lisp that does exactly what you want.
(defun remove (a l)
(cond
((null l) ())
((listp (car l))(cons (remove a (car l))(remove a (cdr l))))
((eq (car l) a) (remove a (cdr l)))
(t (cons (car l) (remove a (cdr l))))
)
)
The function begins with two simple cases, which are: 'list is null' and 'first element is a list'. Following this you will "magically" get the car of the list and the cdr of the list without the given element. To fixed that up to be the answer for the whole list you just have to put them together using cons.