I'm trying to display one value from the list by the function is displaying the entire list instead of one value. Code below using elisp.
(defun element-i (L number)
(if (not L) nil
(if (< (length L) number) nil
(dotimes (i number L)
(pop L)))))
You're returning L from dotimes, which is the remaining list after popping number elements from it.
If you want to get just the element, you should return the first element of L using car.
(defun element-i (L number)
(cond ((null L) nil)
((< (length L) number) nil)
(t (dotimes (i number (car L))
(pop L)))))
I also recommend using cond when you have multiple conditions to test, rather than nested if. And use the null predicate when testing a list; not should be used for logical contexts.
Related
When I was trying to check the number is equal to any element in list, I get the following error:
'NIL' is not of the expected type 'NUMBER'
(defun check-num (li n)
(cond
((= n (car li)) t)
((not (= n (car li))) (check-num (cdr li) n))
((not (= n (car li))) nil)))
(check-num '(1 2 3 4 5) 6)
I found that the problem occur when it try to excute the function 'check-num' with the empty list with the number entered after perform all checking.
The error come out when the compiler try to perform the following function:
(check-num nil 6)
The immediate problem is that you never check for the end of the list. The car of the empty list is nil again. = compares numbers. Nil is not a number.
Check for the end of the list first. Some minor stylistic issues: when using conses as a list, use first and rest instead of car and cdr, name things as they are (list), use proper formatting.
(defun check-num (list n)
(cond ((endp list) nil) ; <-
((= (first list) n) t)
(t (check-num (rest list) n))))
However, it should be noted that there are several ways already in the standard to achieve this check, e. g.:
(member n list)
(find n list)
I am trying to write a function that takes only a list as a parameter and counts the number of times the symbol a appears in the list, without counting any a's in a sublist within the list.
I am very new to Lisp so please use as basic code as possible so I could understand what it is doing, even if it is inefficient.
(defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
So (times '(a b (a) c)) should return 1. However I am getting the error that with this line times is getting two arguments when it should be getting one.
There are multiple ways to implement this in Common Lisp. The example should be small enough for you to follow (test them).
Recursive implementation
Your approach is fine, except you have small errors (in addition to the other ones reported in comments):
Do not use SETF for undeclarded variables.
Do not return NIL in the base case: your function should return a number.
Also, your code coud be better formatted, and you should use longer names (lowercase l in particular is hard to read)
Here is a modified version:
(defun times (list element)
(cond
((null list) 0)
((equal (car list) element) (1+ (times (cdr list) element)))
(t (times (cdr list) element))))
Example
Let's TRACE the function:
CL-USER> (trace times)
Here is the execution trace:
CL-USER> (times '(a b c d a f a) 'a)
0: (TIMES (A B C D A F A) A)
1: (TIMES (B C D A F A) A)
2: (TIMES (C D A F A) A)
3: (TIMES (D A F A) A)
4: (TIMES (A F A) A)
5: (TIMES (F A) A)
6: (TIMES (A) A)
7: (TIMES NIL A)
7: TIMES returned 0
6: TIMES returned 1
5: TIMES returned 1
4: TIMES returned 2
3: TIMES returned 2
2: TIMES returned 2
1: TIMES returned 2
0: TIMES returned 3
3
You can see that the call stack grows for each and every element visited in the list. It is usually a bad practice, especially when the recursive function is basically implementing a loop.
Loops
Use a simple LOOP:
(defun times (list element)
(loop for value in list count (equal value element)))
Alternatively, use DOLIST:
(defun times (list element)
(let ((counter 0))
(dolist (value list counter)
(when (equal element value)
(incf counter)))))
Here above, counter is a local variable introduced by LET. It is incremented with INCF inside the loop, only WHEN the comparison holds. Finally, counter is returned from the dolist (the third parameter indicates which form to evaluate to have the result value). The return value of dolist is also the return value of the let and the whole function.
This can be rewritten also with DO:
(defun times (list element)
(do ((counter 0)) ((null list) counter)
(when (equal element (pop list))
(incf counter))))
The first list in do introduces bindings, the second list is a termination test (here we stop when the list is empty) followed by a result form (here, the counter). Inside the body of the loop, we POP elements from the input list and do the comparison, as before.
Tail-recursive implementation
If you want to keep a recursive implementation, add an accumulator and compute all the intermediate results before entering a recursive evaluation. If all results are passed as function arguments, there is no need to keep track of intermediate results at each step of the recursion, which eliminates the need to even allocate stack frames. The ability to perform tail-call elimination is not expressly required by the specification of the language, but it is typically available in most implementations.
(defun times (list element)
(labels ((recurse (list counter)
(cond
((null list) counter)
((equal (first list) element)
(recurse (rest list) (1+ counter)))
(t (recurse (rest list) counter)))))
(recurse list 0)))
Here above, recurse is a local recursive function introduced by LABELS, which accepts a counter parameter. The difference with the original recursive function is that when the list is empty, it returns the current value of counter instead of zero. Here, the result of recurse is always the same as the value returned by recursive invocations: the compiler can just rebind inputs and perform a jump instead of allocating intermediate frames.
Higher-order functions
Here are yet two other ways, based on higher-order functions.
First, the usual way to define functions with accumulators is with REDUCE (known as fold in other languages). There is no explicit mutation:
(defun times (list element)
(reduce (lambda (counter value)
(if (equal value element)
(1+ counter)
counter))
list
:initial-value 0))
The anonymous function accepts the current state of the accumulator, the current value being visited in the list, and shall compute the next state of the accumulator (the counter).
Alternatively, call MAP with a nil first argument, so that the iteration is only done for effects. The anonymous function established by the LAMBDA form closes over the local counter variable, and can increment it when comparison holds. It is similar to the previous dolist example w.r.t. incrementing the counter through side-effects, but the iteration is done implicitly with map.
(defun times (list element)
(let ((counter 0))
(map ()
(lambda (value)
(when (equal value element)
(incf counter)))
list)
counter))
Built-in
For your information, there is a built-in COUNT function:
(defun times (list element)
(count element list :test #'equal))
Here is some code which might help. It uses tail recursion and defines a helper function which is called recursively and keeps track of the number of times the symbol 'a appears with the argument count. The helper function takes two arguments, but the functino count-a takes one. Count-a calls the helper with the list l and the total number of times it has counted the symbol 'a at the beginning, which is zero to kick off the recursive calls.
(defun count-a (l)
(labels ((helper (x count)
(if (equalp 'a (car x)) (incf count))
(cond ((null x) count)
(t (helper (cdr x) count)))))
(helper l 0)))
You can also use the loop macro:
(defun count-a-with-a-loop (l)
(loop for i in l count (equalp 'a i))\
Or as Coredump points out:
(defun count-a-with-count (l)
(count 'a l :test #'equal))
Note the '# character before equal lets the Lisp interpreter know that equal is a function, known as a reader macro.
If you use a Lisp compiler (like SBCL) you might see this:
* (defun times (l)
(setf x 'a)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x(cdr l)))))
; in: DEFUN TIMES
; (TIMES X (CDR L))
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; The function was called with two arguments, but wants exactly one.
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 3 WARNING conditions
The Lisp compiler tells you that there are three errors in your code.
Let's fix the undefined variable problem first, by introducing a local variable x:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l))))))
Now, we look at the other two: you call TIMES with two arguments.
We can just remove the x argument, since it is not needed:
(defun times (l)
(let ((x 'a))
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times (cdr L))))
(t (times (cdr l))))))
It may be more useful to be able to search for more things, so we add x to the argument list and add it to the call arguments.
(defun times (x l)
(cond
((null l) nil)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Now the function should always return a number, not NIL for an empty list:
(defun times (x l)
(cond
((null l) 0)
((equal x (car l)) (+ 1 (times x (cdr L))))
(t (times x (cdr l)))))
Since Lisp has functions like first and rest, we can replace car and cdr:
(defun times (x l)
(cond
((null l) 0)
((equal x (first l)) (+ 1 (times x (rest l))))
(t (times x (rest l)))))
I'm a newbie in LISP. I'm trying to write a bubble sort function in LISP.
This is what I've done so far.
(defun mysort (x)
(if (null x) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
I'm getting an error
NIL is not a real number
When I modified the code like (after referring several codes)-
(defun mysort (x)
(if (null (cdr x)) x
(if (< (car x) (cadr x))
(cons (car x) (mysort (cdr l)))
(cons (cadr x) (mysort (cons (car x) (cddr x)))))))
Now it works fine.
Why does replacing
(if (null x) x...)
with
(if (null (cdr x)) x...)
make a difference?
Also, I'm calling mysort from another function to run it (length x) number of times. Is it possible to achieve complete sorting in a single recursive loop, only using the basic functions?
If you want to see if the first element is smaller than the second element, then the list needs to have at least two elements.
If there is only one element, CADR returns NIL. This is not a number.
CL-USER 18 > (cadr '(1))
NIL
Your Lisp system should not only tell you the error, but also the function where it occurred. Here: the function <.
Using (null (cdr list)) is a good way to test if there is a second element. A typical error would be to call LENGTH, which is inefficient.
To do a comparison you need at least two elements so checking if x is NIL is not enough.
Checking if (cdr x) is NIL is a nice way to check that the list length is at least two because NIL is special and even if it's not a cons cell it's guaranteed that (cdr NIL) is NIL.
The error you were getting is because NIL is not a number thus you cannot compare with < a number with it and this was happening when executing (< (car x) (cadr x)) when x was a list with a single element.
About sorting in a single recursive call you could use this definition of sorting:
an empty list is sorted
a non-empty list is sorted if the first element is the minimum of the list and the rest of the list is sorted.
This leads to
(defun mysort (x)
(if x
(let ((minimum (reduce #'min x)))
(cons minimum
(mysort (remove minimum x :count 1))))))
That, by the way, is a very inefficient way to do the sorting.
This is the Common Lisp code:
(defun take (L)
(if (null L) nil
(cons (car L) (skip (cdr L)))))
(defun skip (L)
(if (null L) nil
(cons (car L) (take (cdr L)))))
The idea here is that, "take" will give all the odd sequence elements in the input list and "skip" will give all the even sequence elements in the input list. However, in both cases the entire list is returned.
What is the error in this code? Is this something to do with how CL handles lists, because the similar code in SML gives the desired output.
fun take(lst) =
if lst = nil then nil
else hd(lst)::skip(tl(lst))
and
skip(lst) =
if lst = nil then nil
else hd(lst)::take(tl(lst));
To expound on what Sylwester has said, your skip is wrong in both Lisp and SML. It should be
(defun take (L) ; even-indexed elements of a list L
(if (not (null L))
(cons (car L) (skip (cdr L)))))
(defun skip (L) ; odd-indexed elements of a list L
(if (not (null L))
(take (cdr L))))
and
fun take(lst) =
if lst = nil then nil
else hd(lst)::skip(tl(lst))
and
skip(lst) =
if lst = nil then nil
else take(tl(lst));
The take and skip are identical so that is no mystery. skip should just tail call instead of cons-ing. It's the consing that makes the return here.
It's worth pointing out that indexing in Common Lisp (like many other programming languages) starts with 0, so the even-indexed elements of a list are the first, the third, the fifth, and so on, since those have indices 0, 2, 4, etc. It's also worth noting that in Common Lisp, you can take the rest of the empty list and get back the empty list. (You can't do this in every Lisp, though. E.g., in Scheme it's an error to call cdr on something that's not a pair.) This means that you can implement even-elements and odd-elements rather easily. even-elementsjust returns a list of the first element, and the odd elements of the rest of the list. odd-elements returns the even-elements of the rest of the list:
(defun even-elements (list)
(if (endp list) list
(list* (first list) (odd-elements (rest list)))))
(defun odd-elements (list)
(even-elements (rest list)))
These behave in the expected fashion:
CL-USER> (even-elements '(0 1 2 3 4 5))
(0 2 4)
CL-USER> (odd-elements '(0 1 2 3 4 5))
(1 3 5)
Of course, if you note that the call to (odd-elements x) is just a call to (even-elements (rest x)), we could have implemented even-elements as follows, and had the same result:
(defun even-elements (list)
(if (endp list) list
(list* (first list) (even-elements (rest (rest list))))))
I want to create a function in lisp that receives a number and a list of pairs and iterates through the list of pairs and removes the ones in which the result of the division between the first element of the pair, and the second element of the same pair is different from the number passed as an argument. In the end it returns a list with only the ones in which the result of the division is the same.
I have the following code so far:
(defun retira-terco(num l1)
(cond ((null l1) ())
((not (equal num (/ (car(first l1)) (cdr(first l1)))))
(retira-terco num (rest l1)))
(t (cons (first l1) (retira-terco num (rest l1))))))
When I try to run this example with a real example I get the following error:
Error: `(1)' is not of the expected type `NUMBER'
What am I doing wrong?
The problem with your code is in this line:
(/ (car(first l1)) (cdr(first l1)))
(car (first l1)) evaluates to a number, but (cdr (first l1)) evaluates to a list. You probably meant (cadr (first l1)).
That said, this code isn't that great from a lispiness point of view. You have a condition you want to filter on. Use higher order programming to express that more like this:
(defun foo (num lst)
(remove-if (lambda (item)
(equal num
(/ (car item)
(cadr item))))
lst)))