I build this function to check if all the "var" on the list are numbers.
This what i tried to do
(defun check6 (list)
(if (null list) 'TRUE)
(if (not (numberp(first list))) nil)
(check6 (rest list)))
But always i get stack overflow.
Why please?
The stack overflow is due to the fact that you have several unrelated if, so that they produce a value which is not consumed and continue to execute the rest of the body of the function. This means that check6 is never terminated and causes the overflow.
If you paste your code in a proper editor, which automatically align the lines of code, you could discover that the editor produces this alignment:
(defun check6 (list)
(if (null list)
'TRUE) ; only one branch, no else branch, continue to the next form
(if (not (numberp(first list)))
nil) ; again only one branch, continue to the next form
(check6 (rest list))) ; infinite loop
If you want to use the if special operator, you should remember that it has two cases, for when the condition is true and when it is false, and should nest the forms in this way (again with the proper alignment):
(defun check6 (list)
(if (null list)
t
(if (not (numberp (first list)))
nil
(check6 (rest list)))))
But Common Lisp has the much more convenient syntax for concatenating conditions, cond:
(defun check6 (list)
(cond ((null list) t)
((not (numberp (first list))) nil)
(t (check6 (rest list)))))
Finally, note that there are other ways to solve your problem, either by using iteration:
(defun check6 (list)
(loop for element in list always (numberp element)))
or with high-level functions, in a still more concise way:
(defun check6 (list)
(every #'numberp list))
You get a stack overflow because the function never terminates.
The result of a function in Lisp is the value of the last expression in the function's body.
In your case that is (check6 (rest list)).
I suspect that you're thinking of some other language, where this might be written something like (in a completely fictitious language):
bool check6(List list)
{
if (list.empty())
return true;
if (!isNumber(list.head()))
return false;
return check6(list.tail());
}
but your conditionals don't return their results from the function; their results are just discarded since you're not doing anything with them.
In the fictitious language above, your function would be
bool check6(List list)
{
if (list.empty())
true;
if (!isNumber(list.head()))
false;
return check6(list.tail());
}
where you can probably see what's going wrong.
I personally find multi-pronged conditionals hard to follow compared to a logical expression.
If you write down the conditions for when a list is all numbers:
the list is empty, or
its head is a number and
its tail is all numbers
it's straightforward to translate into Lisp:
(defun check6 (list)
(or (null list)
(and (numberp (first list))
(check6 (rest list)))))
In the fictitious language,
bool check6(List list)
{
return list.empty() || (isNumber(list.head()) && check6(list.tail()));
}
But once you get acquainted with higher-order functions, you would probably write
(defun check6 (list)
(every #'numberp list))
which might be the most Lisp-y solution.
You should definitely take a close look at the different ways that Renzo has written the function, but your code can be patched up by returning from the function early:
(defun check6 (list)
(if (null list) (return-from check6 'TRUE))
(if (not (numberp(first list))) (return-from check6 nil))
(check6 (rest list)))
Related
I want to solve a lisp function that returns a NUMBER(count) of numbers which are greater than the first number in the list.The list is a linear list of numbers.
(defun foo (lst)
(cond ((null lst) 0)
(car = k)
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
My problem is that I cannot keep the first element and compare it with the others.
Let's take apart your problem:
You have a set of numbers. Really, you have a “special” first number, and then the rest of them. Specifically, you probably want only real numbers, because “less than” does not make sense in terms of complex (imaginary) numbers.
You can use first to get the first number from the list, and rest for the others.
Of these, you want to count any that are not greater than the first.
So let's start with sort of pseudocode
(defun count-numbers-greater-than-first (list)
;; split out first and rest
;; call the real count function
)
Well, we know now that we can use first and rest (also, as you used, historically car and cdr), so:
(defun count-numbers-greater-than-first (list)
(count-numbers-greater-than (first list) (rest list))
You already probably know that > is used to test whether real numbers are greater than one another.
A quick look at the CLHS reveals a nice function called count-if
(defun count-numbers-not-greater-than (reference other-numbers)
(count-if ??? other-numbers))
The ??? needs to be an object of function type, or the name of a function. We need to “curry” the reference (first number) into that function. This means we want to create a new function, that is only used for one run through the count-if, that already has “closed over” the value of reference.
If we knew that number would always be, say, 100, that function would look like this:
(defun greater-than-100 (number)
(> number 100))
That function could then get used in the count-if:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (function greater-than-100)
other-numbers))
(defun count-numbers-greater-than (reference other-numbers)
(count-if #'greater-than-100 other-numbers))
But that doesn't solve the problem of getting the reference number “curried” into the function.
Without reaching for Alexandria (I'll explain in a moment), you can use a lambda form to create a new, anonymous function right here. Since reference is available within count-numbers-not-greater-than, you can use its value within that lambda. Let's convert for 100 first:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number 100))
other-numbers))
Now we can use reference:
(defun count-numbers-greater-than (reference other-numbers)
(count-if (lambda (number) (> number reference))
other-numbers))
And, in fact, you could even merge this back into the other function, if you wanted:
(defun count-numbers-greater-than-first (list)
(count-if (lambda (number) (> number (first list)))
(rest list)))
That Alexandria thing
But, what about Alexandria? Alexandria is a collection of super-useful utility functions that's available in Quicklisp or elsewhere.
(ql:quickload "alexandria")
(use-package #:alexandria)
Of course, you'd normally use it in your own defpackage
(defpackage my-cool-program
(:use :common-lisp :alexandria))
Two of the things it provides are curry and rcurry functions. It turns out, that lambda function in there is a really common case. You have an existing function — here, > — that you want to call with the same value over and over, and also some unknown value that you want to pass in each time.
These end up looking a lot like this:
(lambda (x) (foo known x))
You can use curry to write the same thing more concisely:
(curry #'foo known)
It also work with any number of arguments. RCurry does the same, but it puts the unknown values “x” at the left, and your known values at the right.
(lambda (x) (foo x known)) = (rcurry #'foo known)
So another way to write the count-if is:
(defun count-numbers-greater-than-first (list)
(count-if (rcurry #'> (first list))
(rest list)))
* (count-numbers-greater-than-first '(10 9 8 7 11 12))
2
Your function indented correctly looks like this:
(defun foo (lst)
(cond ((null lst) 0)
(car = k) ; strange cond term
((> (car lst) k)
(1+ (foo (cdr lst))))
(T (foo (cdr lst)))))
I have commented the second term in your cond. It is quite strange. It first evaluates the variable car (not the function #'car). If car is not nil it first evaluates the variable = (not the function #'=) and since it is not the last consequent expression in the cond term it throws that away and returns the last which is k.
Secondly you write that you say you use the first element as comparison, however you call it k in your function but it is not defined anywhere. You need to do something before you do the recursion and thus you cannot let the actual function do the recursion since it will take the first element each time. Here is where labels can be used:
;; didn't call it foo since it's not very descriptive
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list)
(cond ((null list) 0)
((> (car list) first)
(1+ (helper (cdr list))))
(t (helper (cdr list))))))
(helper (cdr list)))))
Of course. Since you now have the possibility to add more arguments I would have added an accumulator:
(defun count-larger-than-first (list)
(let ((first (car list)))
(labels ((helper (list acc)
(cond ((null list) acc)
((> (car list) first)
(helper (cdr list) (1+ acc)))
(t (helper (cdr list) acc)))))
(helper (cdr list) 0))))
And of course recursion might blow the stack so you should really write it without in Common Lisp:
(defun count-larger-than-first (list)
(let ((first (car list)))
(loop :for element :in (cdr list)
:counting (> element first))))
There are higher order functions that count too which might be more suitable:
(defun count-larger-than-first (list)
(let ((first (car list)))
(count-if (lambda (element) (> element first))
(cdr list))))
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)))
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))))))
The code below server to show the number of integer in a list.
(defun isNum (N)
(and (<= N 9) (>= N 0)))
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond
((null list) nil)
(((and (<= N 9) (>= N 0))) item)(incf count))
(setq(0 + count))))))
I get the error A' is not of the expected typeREAL' when I run the command
(count-numbers '(3 4 5 6 a 7 b) )
I'm surprised it runs at all, given that your cond is improperly constructed, you switch to infix notation in the unnecessarily side-effect-generating bit of your code and you're using unbound variables in count-numbers. Hypothetically, if it did run, that error sounds about right. You're doing numeric comparisons on a parameter (and those error on non-numeric input).
I've got my codereview hat on today, so lets go through this a bit more in-depth.
Lisp (it actually doesn't matter which, afaik this applies to CL, Scheme and all the mongrels) uses lower-case-snake-case-with-dashes, and not lowerCamelCase for variable and function names.
(defun is-num (n)
(and (<= n 9) (>= n 0)))
Common Lisp convention is to end a predicate with p or -p rather than begin them with is-. Scheme has the (IMO better) convention of ending predicates with ? instead
(defun num-p (n)
(and (<= n 9) (>= n 0)))
((and (<= N 9) (>= N 0))) is not how you call a function. You actually need to use its name, not just attempt to call its body. This is the source of one of the many errors you'd get if you tried to run this code.
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond
((null list) nil)
((num-p item) item)(incf count))
(setq(0 + count))))))
numberp already exists, and does a type check on its input rather than attempting numeric comparisons. You should probably use that instead.
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond
((null list) nil)
((numberp item) item)(incf count))
(setq(0 + count))))))
((numberp item) item) (incf count)) probably doesn't do what you think it does as a cond clause. It actually gets treated as two separate clauses; one checks whether item is a number, and returns it if it is. The second tries to check the variable incf and returns count if it evaluates to t (which it doesn't, and won't). What you seem to want is to increment the counter count when you find a number in your list, which means you should put that incf clause in with the item.
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond ((null list) nil)
((numberp item)
(incf count)
item))
(setq (0 + count)))))
(setq (0 + count)) is the wrong thing for three reasons
You seem to have tripped back into infix notation, which means that the second bit there is actually attempting to call the function 0 with the variables + and count as arguments.
You don't have a second part to the setq, which means you're trying to set the above to NIL implicitly.
You don't actually need to set anything in order to return a value
At this point, we finally have a piece of code that will evaluate and run properly (and it doesn't throw the error you mention above).
(defun count-numbers (list)
(let ((count 0))
(dolist (item list count)
(cond ((null list) nil)
((numberp item)
(incf count)
item))
count)))
dolist is an iteration construct that does something for each element in a given list. That means you don't actually need to test for list termination manually with that cond. Also, because dolist doesn't collect results, there's no reason to return item to it. You're also unnecessarily shadowing the local count you declare in the let.
(defun count-numbers (list)
(let ((count 0))
(dolist (item list)
(when (numberp item) (incf count)))
count))
As usual, you can do all this with a simpler loop call.
(defun count-numbers (list)
(loop for item in list
when (numberp item) sum 1))
which makes the counter implicit and saves you from needing to return it manually. In fact, unless this was specifically an exercise to write your own iteration function, Common Lisp has a built in count-if, which takes predicate sequence [some other options] and returns the count of items in sequence that match predicate. If you wanted to name count-numbers specifically, for stylistic reasons, you could just
(defun count-numbers (list) (count-if #'numberp list))
and be done with it.
In conclusion, good try, but please try reading up on the language family for realzies before asking further questions.
Yet another way to do it would be:
(reduce
#'(lambda (a b)
(if (numberp b) (1+ a) a))
'(3 4 5 6 a 7 b) :initial-value 0) ; 5
I.e. process the sequence in a way that you are given at each iteration the result of the previous iteration + the next member of the sequence. Start with zero and increment the result each time the element in the sequence is a number.
EDIT
Sorry, I haven't seen Inaimathi mentioned count-if. That would be probably better.
I wrote a test function to test my understanding of "return-from" in Lisp
(defun testp (lst)
(mapc #'(lambda (x y)
(if (null lst)
(return-from testp t)))
lst
(cdr lst)))
I think the test (testp 'nil) should return T but it returns NIL.
Could you please help my understanding of why it returns NIL?
Many thanks.
You call MAPC over two empty lists.
How should the LAMBDA function ever be used if the lists don't have any elements to map over?
Btw., you can write 'list' instead of 'lst'.
(defun testp (list)
(mapc #'(lambda (x y)
(if (null list)
(return-from testp t)))
list
(cdr list)))
Normally, mapc would apply your lambda to each element of a list. My guess (I don't use Common Lisp) is that since mapc has no elements in the list to operate on, your lambda never gets called at all, and as a result the return value of your function is the return value of mapc, which (since it mapped over nothing) is nil.