Single test recursion - how to create the "no result found" return value? - recursion

I am working on a recursive function that looks for the first odd number in a list. It works as expected.
But when there is NO odd number in a list, it returns an error. Id like to control this error with some sort of message that says "no odd values found".
Single Test Recursion Function
(defun find-first-odd (x)
(cond ((oddp (first x)) (first x))
(t (find-first-odd (rest x)))))
(find-first-odd '(2 2 10 3 4 6 4)) ; => 3
(find-first-odd '(2 2 10 4 6 4)) ;=> value nil is not an integer
(find-first-odd '(2 2 10 4 6 4 . 2)) ;=> 2 is not type list

You need to test for the list being empty and do the appropriate thing. In general any function which searches a list recursively needs a termination test, and thus looks something like:
(defun search-list-for (l ...)
(cond ((null l)
...)
(<(first l) is what we're after>
...)
(t
(search-list-for (rest l) ...))))
and in this case:
(defun find-first-odd (l)
(cond
((null l)
nil) ;or whatever
((oddp (first l))
(first l))
(t
(find-first-odd (rest l)))))
You are lucky that, for your particular function, while (first '()) is perfectly legal in CL, it is not a number and so you get an error. In general you'll get failure to terminate:
(defun contains-thing-p/broken (l thing)
(cond
((eql (first l) thing)
t)
(t
(contains-thing-p/broken (rest l) thing))))
will not terminate if thing is not in the list, and must be written using the above skeleton instead:
(defun contains-thing-p (l thing)
(cond
((null l)
nil)
((eql (first l) thing)
t)
(t
(contains-thing-p (rest l) thing))))

Let's do it in a strange way...
First I define a function which returns the first odd number, if there is one. If there is none, then there will be an error signalled.
(defun %find-first-odd (list)
(etypecase list
((cons (satisfies oddp) list) (first list))
((cons T list) (find-first-odd (rest list)))))
We have types CONS, (SATISFIES ODDP), LIST and T.
The first clause is selected when there is a cons cell with an odd number as its car. The second clause is selected when it is a cons cell with a list as the cdr.
If none of the above clauses are selected, then there will beautomagically an error signalled.
Now I define a function calling the above.
If there is an error, it signals a new error with a specific error message saying that in this specific list there is no odd number.
(defun find-first-odd (list)
(handler-case (%find-first-odd list)
(error () (error "No odd number found in ~a" list))))
Testing it:
CL-USER > (find-first-odd '(2 4 6))
Error: No odd number found in (2 4 6)

Related

Function call stack overflow

I get the error message below when I run my code. The code below add the elements that are not nil.
(summit2 '(0 nil 1 2))
Error: Received signal number -3 (function call stack overflow (delayed response))
[condition type: ASYNCHRONOUS-OPERATING-SYSTEM-SIGNAL]
I have tried changing null with nil. I also tried using eq as opposed to eql.
(defun summit2 (lst)
(if (eql (car lst) null)
(summit2 (cdr lst))
(+ (car lst) (summit2 (cdr lst)))))
the expected output should be 3, the sum of the elements in the list that are not nil
First of all, the check for nil should be done by using the NULL function, so (null (car lst)) in your case. Secondly, your recursion lacks the base case (the error you're getting indicates a stack overflow due to infinite recursion). Now you only distinguish between whether the next element is nil or non-nil. You need a third case to handle the empty list. This suggests the use of COND. You could, for example do something like:
(defun summit2 (lst)
(cond
((null lst)
0)
((null (car lst))
(summit2 (cdr lst)))
(t
(+ (car lst) (summit2 (cdr lst))))))
Some remarks
You can spell your list list, there is no need to abbreviate it to lst.
All branches in your code leads to a recursive call to summit, there is no case where you stop computing the result. This infinite computation takes up stack space, which is why it eventually stops with a stack overflow.
Please indent your code in a conventional way (read for example this style guide)
Notice that the case where an element is nil is not much different than the case where the input list is empty. With the following code, both are handled the same way:
(defun sum (val)
(if (consp val)
(+ (sum (car val))
(sum (cdr val)))
(or val 0)))
This also means the code is able to do more than expected, i.e. you can sum numbers in a tree:
(sum '(0 1 2 nil 4 5 7 (1 2)))
=> 22
And it also works when the input is just an number:
(sum 5)
=> 5

Trying to understanding recursion and why an error is occurring

I am writing a program which takes in a list and outputs true if the elements in the list alternate signs. For example if the first number is positive, the second number must be negative and then the third number must be positive again and so on.
I've tried implementing a simple cond statement (shown in the code) but keep coming across an error in my check-expect. The error states: first: expects only 1 argument, but found 2.
(define (alternating? lst)
(cond [(empty? lst) true]
[(> (first lst) 0)
(cond [(< (first (rest lst) 0)) (alternating? (rest lst))])]
[(< (first lst) 0)
(cond [(> (first (rest lst) 0)) (alternating? (rest lst))])]
[else false]))
When looking at the code, it looks like first does in fact only take in one argument from the list, but the error says that this is not the case.
On lines 3 and 5, you are correctly calling first with one argument, namely lst:
(first lst)
On lines 4 and 6, you are calling first with two arguments, namely (rest lst) and 0:
(first (rest lst) 0)
I think what you want is this:
(< (first (rest lst)) 0)
; ↑ ↑
instead of this:
(< (first (rest lst) 0))
; ↑ ↑

Scheme Function: (show-up-to-n '(4 6 3 -8 3 4) 5) ==> (4 3 -8 3 4)

i am trying to write a function in Scheme that takes in a list and an integer and outputs the same list minus all the members less than the integer... please help. I seem to be unable to add the numbers into a new list that can be outputed.
(define result '())
(display result)
(define nums-less-than-x
(lambda (lst x)
(define impl
(lambda (l1 b result)
(if (null? l1) result
(begin (if (> b (car l1))
(begin (cons (car l1) result)
;(display result)(newline)(newline)
(display (car l1) )(newline))
)
(impl (cdr l1) b result)
))
))
(impl lst x result)
))
(display (show-up '(4 6 3 -8 3 4) 5))
The code juss displays (), an empty list like that, when I run
(display (num-less-than-x '(some list) x))
Your result is never updated. usually I would expect that only when the element is not being a part of the result and otherwise a recursion like:
(impl (cdr l1) b (cons (car l1) result))
I notice that you have put debug output as the last expression in a begin, eg.
(begin
expression-that-does-something
(display ...)
(newline))
Note that the expressions result is not the result, but the result from the newline, typically some undefined value. You need to put your debug stuff first then as the tail the expression your function should return. Alternatively you could make a debug function:
(define (debug expr)
(display expr)
(newline)
expr))
My understanding is that you want the procedure to return the result, not to display it, which is the right way to do it:
(define show-up
(lambda (lst mx)
(if (null? lst)
lst
(let ((c (car lst)))
(if (> c mx)
(show-up (cdr lst) mx)
(cons c (show-up (cdr lst) mx)))))))
Testing:
> (show-up '(4 6 3 -8 3 4) 5)
'(4 3 -8 3 4)
When programming in a functional style, we try to use existing procedures to solve a problem. With that in mind, the preferred solution would be:
(define (show-up-to-n lst x)
(filter (lambda (n) (< n x))
lst))
Also notice that in truly functional code we avoid at all costs procedures that modify state (such as set!), it's a better idea to create a new list with the result.

Reverse list in CLISP

I'm trying to write my own function to reverse list in LISP. The problem is input
(revert '(2 3 (4 5 (6))))
My code looks like this:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l)) (list (car l)))))
It returns
((4 5 (6)) 3 2)
instead of this:
(((6) 5 4) 3 2)
How can I fix it to work correctly?
Since you want to reverse sublists as well, you have to use REVERT on the CAR as well as CDR:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l))
(list (revert (car l))))))
This however requires you to handle the possibility that L might be an atom, which should be returned as is. Since NIL is also an atom you can just change the condition to check for ATOM instead of NULL.
(defun revert (list)
(if (atom list)
list
(append (revert (cdr list))
(list (revert (car list))))))
(revert '(2 3 (4 5 (6))))
;=> (((6) 5 4) 3 2)
In Common Lisp, it's preferred to use full words for names, so it's better to name l list. You could also name the function something like tree-reverse.

Get minimum num recursively from a list

I'm new to lisp and trying to write a recursive function that returns minimum number from a list. It also wants to detect atom. The following code returns error:
(defun minFromList (l)
(cond ((null l) nil) ; Causes error shown below
; (cond ((null l) ) ; Causes the same error
; (cond ((null l) 0) ; It causes always 0 to be the final return val.
((numberp l) l)
((numberp (car l)) (min (car l) (minFromList(cdr l))))
((listp (car l)) (min (minFromList (car l)) (minFromList (cdr l))))
(t nil) ; if all condition doesn't hold just return nil.
)
)
Error:
*** - MIN: NIL is not a real number
Apparently the problem lies in where it returns nil/0 when the given list is null. What's possible workarounds? Thank you.
Environment) Ubuntu 11.10, clisp 2.49
Update) Although I already picked up this as the answer, I welcome if there are other ways especially w/o making new functions if any.
Here's the simplest code I made inspired by the chosen answer.
(defun minNum (a b)
(cond ((null a) b)
((null b) a)
(t (min a b)))
)
Apparently you get an error message because you try to use the result of your function as a number, and said result is nil when the function is called with an empty list as argument, so the evaluation that tries to use the result fails. This is not a Common Lisp problem - you have to decide what to return when the argument is empty. Maybe 0 is a good value, maybe some approximation of minus infinity - only you (or whoever uses your function) can tell.
As for getting the the minimum (or the sum or any other 'reduction') of a list, this is a pattern already handled by the reduce Common Lisp standard function. So min-from-list could look something like:
CL-USER> (defun min-from-list (list &optional (default 0))
(reduce #'min list :initial-value default))
MIN-FROM-LIST
CL-USER> (min-from-list '(1 2 -3))
-3
CL-USER> (min-from-list '(1 2 -3) -7)
-7
CL-USER> (min-from-list '())
0
CL-USER> (min-from-list '() -3)
-3
(the user can specify what the minimum of an empty list is - if none specified, it's 0).
When comparing two numbers, you need to deal with the nil case in some way. This is easy to do. Define your own version of min that satisfies
(min2 nil <x>) = <x>
(min2 <x> nil) = <x>
(min2 <x> <y>) = (min <x> <y>) if <x>, <y> non-null
and use that.
The simplest approach I can think of is to wrap an application of min.
(defun min-or-nil (num-list)
(when num-list (apply #'min num-list)))

Resources