I have written a recursive function that checks a list to see if the element is present in lisp, but there's a stack overflow error - lisp

This is the member p method I tried. (Squash list is a method I made before that takes in the input of a list, and returns a list consisting of only atoms.)
(defun member-p (x y)
(squash-listr y)
(if (listp y)
(if (eq (cdr y) nil) nil)
(t (eq (car y) x) x)
)
(member-p x (cdr y))
)
Test cases (I'll add more, but this is my first one)
(print(member-p '2 '(2 4 5)))
;this test case should return 2 (the first argument of member-p)
Right now I'm getting a stack overflow error. I've checked my parentheses but am unable to find any issues.

Note that member-p is called at the end in every case, even if y is nil. Thus the stack overflow. You should only call member-p in the case if y is not empty.
Further, the result of squash-listr is not used, thus you should ask yourself if it is really needed.

You need something like this:
(defun member-p (value lst)
(if lst
(if (eql value (car lst))
value
(member-p value (cdr lst)))
'nil))
There are two base conditions:
We find the value, return value
We reach the end of the list before finding the value, return 'nil
Otherwise:
We run again on the cdr of the list.
By contrast, you don't have a base case. A value is calculated, which is thrown away, before the function is called again. Because '(listp y) is always true, only the first of the two values is calculated. Compiling the old version in Portacle shows the code that cannot be reached, underlined.
The execution of code can be seen using trace:
(trace member-p)
(member-p 2 '(1 2 3))

Related

Using Lisp: define a function that takes a list and a number and returns true if the number occurs in the list

I am new to lisp and I have a problem, I'm trying to find the number in the list but it is not working. I haven't made the return statement yet
(defun num (x 'y)
(if (member x '(y)) 't nil))
(write (num 10 '(5 10 15 20)))
My output just outputs the nil instead of doing the function and I'm confused of what I am doing wrong.
Solution
(defun member-p (element list)
"Return T if the object is present in the list"
(not (null (member element list))))
The not/null pattern is equivalent to (if (member element list) t nil) but is more common.
In fact, you do not really need this separate function,
member is good enough.
The -p suffix stands for predicate, cf. integerp and upper-case-p.
Your code
You cannot quote lambda list elements, so you need to replace defun num (x 'y) with defun num (x y)
You need not quote t
Quoting '(y) makes no sense, replace it with y.
You do not need to write the function call, the REPL will do it for you.
See also
When to use ' (or quote) in Lisp?
Can you program without REPL on Lisp?
You are almost certainly expected to not just use member, but to write a function which does what you need (obviously in real life you would just use member because that's what it's for).
So. To know if an object is in a list:
if the list is empty it's not;
if the head of the list is equal to the object it is;
otherwise it is in the list if it's in the tail of the list.
And you turn this into a function very straightforwardly:
(defun num-in-list-p (n l)
;; is N in L: N is assumed to be a number, L a list of numbers
(cond ((null l)
nil)
((= n (first l))
t)
(t
(num-in-list-p n (rest l)))))
You could use the built in position function which will return the index of the number if it is in the list:
(position 1 '(5 4 3 2 1))
If you want to define your own function:
CL-USER> (defun our-member(obj lst)
(if(zerop (length lst))
nil
(if(equal(car lst)obj)
T
(our-member obj (cdr lst)))))
OUR-MEMBER
CL-USER> (our-member 1 '(5 4 3 2 1))
T
CL-USER> (our-member 99 '(1 2 3 4 5))
NIL
We can create a function called "our-member" that will take an object (in your case a number) and a list (in your case a list of numbers) as an argument. In this situation our "base-case" will be whether or not the length of the list is equal to zero. If it is and we still haven't found a match, we will return nil. Otherwise, we will check to see if the car of the list (the first element in the list) is equal to the obj that we passed. If so, we will return T (true). However, if it is not, we will call the function again passing the object and the cdr of the list (everything after the car of the list) to the function again, until there are no items left within the list. As you can see, The first example of a call to this function returns T, and the second example call returns NIL.
What makes this utility function a good example is that it essentially shows you the under workings of the member function as well and what is going on inside.

Assignment in Lisp

I have the following setup in Common Lisp. my-object is a list of 5 binary trees.
(defun make-my-object ()
(loop for i from 0 to 5
for nde = (init-tree)
collect nde))
Each binary tree is a list of size 3 with a node, a left child and a right child
(defstruct node
(min 0)
(max 0)
(ctr 0))
(defun vals (tree)
(car tree))
(defun left-branch (tree)
(cadr tree))
(defun right-branch (tree)
(caddr tree))
(defun make-tree (vals left right)
(list vals left right))
(defun init-tree (&key (min 0) (max 1))
(let ((n (make-node :min min :max max)))
(make-tree n '() '())))
Now, I was trying to add an element to one of the binary trees manually, like this:
(defparameter my-object (make-my-object))
(print (left-branch (car my-object))) ;; returns NIL
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
(print (left-branch (car my-object))) ;; still returns NIL
The second call to print still returns NIL. Why is this? How can I add an element to the binary tree?
The first function is just:
(defun make-my-object ()
(loop repeat 5 collect (init-tree)))
Now you define a structure for node, but you use a list for the tree and my-object? Why aren't they structures?
Instead of car, cadr and caddr one would use first, second, third.
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
You set the local variable x to a new value. Why? After the let the local variable is also gone. Why aren't you setting the left branch instead? You would need to define a way to do so. Remember: Lisp functions return values, not memory locations you can later set. How can you change the contents in a list? Even better: use structures and change the slot value. The structure (or even CLOS classes) has following advantages over plain lists: objects carry a type, slots are named, accessors are created, a make function is created, a type predicate is created, ...
Anyway, I would define structures or CLOS classes for node, tree and object...
Most of the code in this question isn't essential to the real problem here. The real problem comes in with the misunderstanding of this code:
(let ((x (left-branch (car my-object))))
(setf x (cons (init-tree) x)))
We can see the same kind of behavior without user-defined structures of any kind:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(let ((x (car cell)))
(setf x 3)
(print cell))) ; prints (1 . 2)
If you understand why both print statements produce (1 . 2), then you've got enough to understand why your own code isn't doing what you (previously) expected it to do.
There are two variables in play here: cell and x. There are three values that we're concerned with 1, 2, and the cons-cell produced by the call (cons 1 2). Variables in Lisp are often called bindings; the variable, or name, is bound to a value. The variable cell is bound to the the cons cell (1 . 2). When we go into the inner let, we evaluate (car cell) to produce the value 1, which is then bound to the variable x. Then, we assign a new value, 3, to the variable x. That doesn't modify the cons cell that contains the value that x was originally bound to. Indeed, the value that was originally bound to x was produced by (car cell), and once the call to (car cell) returned, the only value that mattered was 1.
If you have some experience in other programming languages, this is directly analogous to something like
int[] array = ...;
int x = array[2]; // read from the array; assign result to x
x = 42; // doesn't modify the array
If you want to modify a structure, you need to setf the appropriate part of the structure. E.g.:
(let ((cell (cons 1 2)))
(print cell) ; prints (1 . 2)
(setf (car cell) 3)
(print cell)) ; prints (3 . 2)

What's the difference between (list nil) and '(nil) in Lisp? [duplicate]

This question already has answers here:
Why does this function return a different value every time?
(4 answers)
Unexpected persistence of data [duplicate]
(1 answer)
Closed 7 years ago.
First of all, let me say I'm a beginner in Lisp. To be honest I have been a beginner for some time now, but there are still many things I don't know well.
While I was writing this question, I came up with a strange bug in my code.
Here is a function that will return the list (0 1 ... n) with the list e appended. It uses rplacd along the way to keep track of the last element, to avoid a final call to last.
For example, (foo 4 '(x)) returns (0 1 2 3 4 x).
The "head" is stored in a, which is not simply nil, because there is only one nil, and never a copy of it (if I understand correctly), hence I can't simply append to nil.
(defun foo (n e)
(let* ((a (list nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
(defun bar (n e)
(let* ((a '(nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
The only difference between these functions is the (list nil) replaced by '(nil) in bar. While foo works as expected, bar always returns nil.
My initial guess is this happens because the original cdr of a is indeed nil, and the quoted list may be considered constant. However, if I do (setf x '(nil)) (rplacd x 1) I get (nil . 1) as expected, so I must be at least partially wrong.
When evaluated, '(nil) and (list nil) produce similar lists, but the former can be considered constant when present in source code. You should not perform any destructive operations on a constant quoted list in Common Lisp. See http://l1sp.org/cl/3.2.2.3 and http://l1sp.org/cl/quote. In particular, the latter says "The consequences are undefined if literal objects (including quoted objects) are destructively modified."
Quoted data is considered a constant. If you have two functions:
(defun test (&optional (arg '(0)))
(setf (car arg) (1+ (car arg)))
(car arg))
(defun test2 ()
'(0))
These are two functions both using the constant list (0) right?
The implementation may choose to not mutate constants:
(test) ; ==> Error, into the debugger we go
The implementation can cons the same list twice (the reader might do that for it)
(test2) ; ==> (0)
(test) ; ==> 1
(test) ; ==> 2
(test) ; ==> 3
(test2) ; ==> (0)
The implementation can see it's the same and hench save space:
(test2) ; ==> (0)
(test) ; ==> 1
(test) ; ==> 2
(test) ; ==> 3
(test2) ; ==> (3)
In fact. The last two behavior might happen in the same implementation dependent on the function being compiled or not.
In CLISP both functions work the same. I also see when disassembling with SBCL that the constant actually is mutated so I wonder if perhaps it has constant folded (cdr '(0)) at compile time and doesn't use the mutated list at all. It really doesn't matter since both are considered good "undefined" behavior.
The part from CLHS about this is very short
The consequences are undefined if literal objects (including quoted
objects) are destructively modified.

Why does an elisp local variable keep its value in this case?

Could someone explain to me what's going on in this very simple code snippet?
(defun test-a ()
(let ((x '(nil)))
(setcar x (cons 1 (car x)))
x))
Upon a calling (test-a) for the first time, I get the expected result: ((1)).
But to my surprise, calling it once more, I get ((1 1)), ((1 1 1)) and so on.
Why is this happening? Am I wrong to expect (test-a) to always return ((1))?
Also note that after re-evaluating the definition of test-a, the return result resets.
Also consider that this function works as I expect:
(defun test-b ()
(let ((x '(nil)))
(setq x (cons (cons 1 (car x))
(cdr x)))))
(test-b) always returns ((1)).
Why aren't test-a and test-b equivalent?
The Bad
test-a is self-modifying code. This is extremely dangerous. While the variable x disappears at the end of the let form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be passed around (just like a number or a list), and, sometimes, modified. This is exactly what you are doing here: the initial value for x is a part of the function object and you are modifying it.
Let us actually see what is happening:
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote (nil)))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1 1))))) (setcar x (cons 1 (car x))) x))
The Good
test-b returns a fresh cons cell and thus is safe. The initial value of x is never modified. The difference between (setcar x ...) and (setq x ...) is that the former modifies the object already stored in the variable x while the latter stores a new object in x. The difference is similar to x.setField(42) vs. x = new MyObject(42) in C++.
The Bottom Line
In general, it is best to treat quoted data like '(1) as constants - do not modify them:
quote returns the argument, without evaluating it. (quote x) yields x.
Warning: quote does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader (see info node
Printed Representation). This means that (a . b) is not
identical to (cons 'a 'b): the former does not cons. Quoting should
be reserved for constants that will never be modified by side-effects,
unless you like self-modifying code. See the common pitfall in info
node Rearrangement for an example of unexpected results when
a quoted object is modified.
If you need to modify a list, create it with list or cons or copy-list instead of quote.
See more examples.
PS1. This has been duplicated on Emacs.
PS2. See also Why does this function return a different value every time? for an identical Common Lisp issue.
PS3. See also Issue CONSTANT-MODIFICATION.
I found the culprit is indeed 'quote. Here's its doc-string:
Return the argument, without evaluating it.
...
Warning: `quote' does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader
...
Quoting should be reserved for constants that will
never be modified by side-effects, unless you like self-modifying code.
I also rewrote for convenience
(setq test-a
(lambda () ((lambda (x) (setcar x (cons 1 (car x))) x) (quote (nil)))))
and then used
(funcall test-a)
to see how 'test-a was changing.
It looks like the '(nil) in your (let) is only evaluated once. When you (setcar), each call is modifying the same list in-place. You can make (test-a) work if you replace the '(nil) with (list (list)), although I presume there's a more elegant way to do it.
(test-b) constructs a totally new list from cons cells each time, which is why it works differently.

LISP disposing of pesky NILs

I have the following filter function that filters out a list, x, that doesn't satisfy the function f.
For example, I call (filter 'evenp '(0 1 2 3)) and get back (NIL 1 NIL 3). But this is exactly my problem. How do I make it so that I just get back (1 3) ?
(defun filter (f x)
(setq h (mapcar #'(lambda (x1)
(funcall f x1))
x))
(mapcar #'(lambda (a b)
(cond ((null a) b)))
h x))
i.e. the problem is right here: (lambda (a b) (cond ( (null a) b) ) ) In my cond I don't have a t , or else statement, so shouldn't it just stop right there and not return nil ? How do I make it "return" nothing, not even nil, if the (cond ( (null a) b) ) isn't satisfied?
Much appreciated. :)
Based on this question it would be:
(remove-if #'evenp '(0 1 2 3))
Ignoring the other questions raised by this post, I'll say that mapcar will always return something for each thing it's mapping over, so you can't use another mapcar to clean up the NILs there. This is what mapcar does -- it walks over the item (or items, if mapping on multiple lists, as your second attempted mapcar does) and collects the result of calling some function on those arguments.
Instead, in this situation, if you had to use mapcar for some reason, and didn't want the NILs, you could use the remove function, i.e. (remove nil (mapcar ...))
Since #stark's answer is posted above, I'll say that the remove-if function there is essentially what you're trying to implement here. (That's where the question of whether or not this is for homework becomes most relevant.)
To answer the more general question of how to splice an arbitrary number of items (including none at all) into the result, mapcan (which is semantically mapcar + append) is useful for that:
(defun filter (f xs)
(mapcan (lambda (x)
(if (funcall f x)
(list x)
nil))
xs))
mapcan is also useful when you want to map an item to multiple results:
(defun multi-numbers (xs)
(mapcan (lambda (x) (list x (+ x x) (* x x))) xs))
(multi-numbers (list 1 2 3))
;=> (1 2 1 2 4 4 3 6 9)