Difference between &rest parameter and list in Common Lisp - lisp

(defun highest (lat)
(cond
((null lat) nil)
((null (cdr lat)) (car lat))
(T (higher (car lat) (highest (cdr lat))))))
(defun higher (a1 a2)
(cond
((> a1 a2) a1)
(T a2)))
This function works as expected:
> (highest '(3 5 1 2 3))
3. Trace: (HIGHEST '(3 5 1 2 3))
4. Trace: (HIGHEST '(5 1 2 3))
5. Trace: (HIGHEST '(1 2 3))
6. Trace: (HIGHEST '(2 3))
7. Trace: (HIGHEST '(3))
7. Trace: HIGHEST ==> 3
6. Trace: HIGHEST ==> 3
5. Trace: HIGHEST ==> 3
4. Trace: HIGHEST ==> 5
3. Trace: HIGHEST ==> 5
But if I change the parameter to &rest:
(defun highest (&rest args)
(cond
((null args) nil)
((null (cdr args)) (car args))
(T (higher (car args) (highest (cdr args))))))
It doesn't behave the same.
> (highest 3 5 1 2 3)
3. Trace: (HIGHEST '3 '5 '1 '2 '3)
4. Trace: (HIGHEST '(5 1 2 3))
4. Trace: HIGHEST ==> (5 1 2 3)
*** - >: (5 1 2 3) is not a real number
EDIT: Sorry, I forgot to mention that I pass the arguments a atoms in the second case. I edited the question to make it more clear.

Try to evaluate (trace highest) before calling (highest 3 2 10). You will then see that the second call looks like this:
(highest '(2 10))
Then the &rest parameter sees one object which happens to be a list.
To correct this, use APPLY. APPLY is like funcall but its last argument must be a list and is treated as if it was 'spliced onto' the function call. Like this:
(apply #'highest (cdr args))

The &rest form collects all the rest of the parameters passed as a list itself. In the case of the highest (&rest args), args is actually a list with an element, a list. That is, in the call, args value is ((3 2 10)).
The second version of highest with the &rest modifier always enters in the second test of the condition, as args is just a list with one element (that happens to be a list). You return the first element of args, which is the list itself, (3 2 10).
The difference with both constructs is that the first version, in which you pass the list as a parameter, the function receives the list as the only parameter of the function. In the case of &rest, all the arguments (in this case just one) are collected into a list (in this case with just one element).
EDIT: As per your edit, as Thomas states in his comment, using &rest implies you have to use apply to call recursively. This is the correct implementation:
(defun highest (&rest args)
(cond
((null args) nil)
((null (cdr args)) (car args))
(T (higher (car args) (apply #'highest (cdr args))))))
(note the apply in the last line).

Related

Racket: Product of even number

I am trying to produce the product of the even numbers in a given list.
I am trying to replicate the following example:
Example:
(product-even-numbers '(2 1 6 3 5))
==> 12
This is my version of the definition for product-even-numbers:
(define (product-even-numbers lst)
(define/match (recurse lst accumulator)
;; A _ pattern matches any syntax object
[(_ _) (* car (recurse cdr))])
(recurse lst 1))
I am getting the following error:
(product-even-numbers '(2 1 6 3 5))
. . recurse: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
I understand that i am missing the second argument, but I do not know what the second argument is supposed to be.
Why are you using pattern matching? this would be easier to understand without it, and first of all you need to get the recursion and the logic right:
(define (product-even-numbers lst)
(define (recurse lst acc)
(cond ((null? lst) acc)
((even? (car lst)) (recurse (cdr lst) (* (car lst) acc)))
(else (recurse (cdr lst) acc))))
(recurse lst 1))
In this case, it's clear that the second argument is the accumulated product we have so far. And we need to consider three cases: empty list, even element, odd element. For example:
(product-even-numbers '(2 1 6 3 5))
=> 12
(define (product-even-numbers lst)
(local [(define tmp (foldr * 1 (filter even? lst)))]
(if (= 1 tmp) 'nothing tmp)))
If output 1 means no any even number.
(define (product-even-numbers2 lst)
(foldr * 1 (filter even? lst))) ; or use (apply * (filter even? lst))

IN Racket Define a function that takes two arguments

I need some one can explain for me to how to do this please
Define a function that takes two arguments, a list of numbers and a single number (the threshold). It should return a new list that has the same numbers as the input list, but with all elements greater than the threshold number removed. You may not use the built-in filter function as a helper
function. Your implementation must be recursive.
INPUT: A list of numbers and a single atomic number.
OUTPUT: A new list of numbers that contains only the numbers from the original list that are strictly “less than” (<), i.e. below the threshold number.
Example:
> (upper-threshold '(3 6.2 7 2 9 5.3 1) 6)
'(3 2 5.3 1)
> (upper-threshold '(1 2 3 4 5) 4)
'(1 2 3)
> (upper-threshold '(4 8 5 6 7) 6.1)
'(4 5 6)
> (upper-threshold '(8 3 5 7) 2)
'()
This what I have so far but I receve error
(define (upper-threshold pred lst)
(cond [(empty? lst) empty]
[(pred (first lst))
(cons (first lst) (upper-threshold pred (rest lst)))]
[else (upper-threshold pred (rest lst))]))
; (threshold (lambda (x) (> x 5)) '(1 6 7))
Your implementation doesn't have the same arguments as your assignment.
You need something that compares the first element with the second argument so see it its larger or not, then either (cons (car lst) (upper-treshold (cdr lst) streshold)) to include the first element in the result or (upper-treshold (cdr lst) treshold) to not include it.
(define (upper-threshold lst treshold)
(cond [(empty? lst) empty]
[(> (car lst) treshold)
(cons (first lst) (upper-threshold (rest lst) treshold))]
[else (upper-threshold (rest lst) treshold)]))
I don't quite understand your code. However, you might be looking for something like this:
(define (upper-threshold lst theshold)
(cond
((null? lst) '())
((< (car lst) theshold)
(cons (car lst)
(upper-threshold (cdr lst) theshold)))
(else (upper-threshold (cdr lst) theshold))))
If your purpose is to implement the standard function filter, perhaps you should write the code some another way.
It appears that you've taken a filter function and renamed it as upper-threshold. It's true that these two are related. I would suggest trying to build upper-threshold from scratch, using the design recipe:
http://www.ccs.neu.edu/home/matthias/HtDP2e/
When you get confused, refer to existing functions that you have, including the definition of filter that you have here. Your example may be slightly harder to understand because it uses lambda.

reversing list in Lisp

I'm trying to reverse a list in Lisp, but I get the error: " Error: Exception C0000005 [flags 0] at 20303FF3
{Offset 25 inside #}
eax 108 ebx 200925CA ecx 200 edx 2EFDD4D
esp 2EFDCC8 ebp 2EFDCE0 esi 628 edi 628 "
My code is as follows:
(defun rev (l)
(cond
((null l) '())
(T (append (rev (cdr l)) (list (car l))))))
Can anyone tell me what am I doing wrong? Thanks in advance!
Your code as written is logically correct and produces the result that you'd want it to:
CL-USER> (defun rev (l)
(cond
((null l) '())
(T (append (rev (cdr l)) (list (car l))))))
REV
CL-USER> (rev '(1 2 3 4))
(4 3 2 1)
CL-USER> (rev '())
NIL
CL-USER> (rev '(1 2))
(2 1)
That said, there are some issues with it in terms of performance. The append function produces a copy of all but its final argument. E.g., when you do (append '(1 2) '(a b) '(3 4)), you're creating a four new cons cells, whose cars are 1, 2, a, and b. The cdr of the final one is the existing list (3 4). That's because the implementation of append is something like this:
(defun append (l1 l2)
(if (null l1)
l2
(cons (first l1)
(append (rest l1)
l2))))
That's not exactly Common Lisp's append, because Common Lisp's append can take more than two arguments. It's close enough to demonstrate why all but the last list is copied, though. Now look at what that means in terms of your implementation of rev, though:
(defun rev (l)
(cond
((null l) '())
(T (append (rev (cdr l)) (list (car l))))))
This means that when you're reversing a list like (1 2 3 4), it's like you're:
(append '(4 3 2) '(1)) ; as a result of (1)
(append (append '(4 3) '(2)) '(1)) ; and so on... (2)
Now, in line (2), you're copying the list (4 3). In line one, you're copying the list (4 3 2) which includes a copy of (4 3). That is, you're copying a copy. That's a pretty wasteful use of memory.
A more common approach uses an accumulator variable and a helper function. (Note that I use endp, rest, first, and list* instead of null, cdr, car, and cons, since it makes it clearer that we're working with lists, not arbitrary cons-trees. They're pretty much the same (but there are a few differences).)
(defun rev-helper (list reversed)
"A helper function for reversing a list. Returns a new list
containing the elements of LIST in reverse order, followed by the
elements in REVERSED. (So, when REVERSED is the empty list, returns
exactly a reversed copy of LIST.)"
(if (endp list)
reversed
(rev-helper (rest list)
(list* (first list)
reversed))))
CL-USER> (rev-helper '(1 2 3) '(4 5))
(3 2 1 4 5)
CL-USER> (rev-helper '(1 2 3) '())
(3 2 1)
With this helper function, it's easy to define rev:
(defun rev (list)
"Returns a new list containing the elements of LIST in reverse
order."
(rev-helper list '()))
CL-USER> (rev '(1 2 3))
(3 2 1)
That said, rather than having an external helper function, it would probably be more common to use labels to define a local helper function:
(defun rev (list)
(labels ((rev-helper (list reversed)
#| ... |#))
(rev-helper list '())))
Or, since Common Lisp isn't guaranteed to optimize tail calls, a do loop is nice and clean here too:
(defun rev (list)
(do ((list list (rest list))
(reversed '() (list* (first list) reversed)))
((endp list) reversed)))
In ANSI Common Lisp, you can reverse a list using the reverse function (nondestructive: allocates a new list), or nreverse (rearranges the building blocks or data of the existing list to produce the reversed one).
> (reverse '(1 2 3))
(3 2 1)
Don't use nreverse on quoted list literals; it is undefined behavior and may behave in surprising ways, since it is de facto self-modifying code.
You've likely run out of stack space; this is the consequence of calling a recursive function, rev, outside of tail position. The approach to converting to a tail-recursive function involves introducing an accumulator, the variable result in the following:
(defun reving (list result)
(cond ((consp list) (reving (cdr list) (cons (car list) result)))
((null list) result)
(t (cons list result))))
You rev function then becomes:
(define rev (list) (reving list '()))
Examples:
* (reving '(1 2 3) '())
(3 2 1)
* (reving '(1 2 . 3) '())
(3 2 1)
* (reving '1 '())
(1)
If you can use the standard CL library functions like append, you should use reverse (as Kaz suggested).
Otherwise, if this is an exercise (h/w or not), you can try this:
(defun rev (l)
(labels ((r (todo)
(if todo
(multiple-value-bind (res-head res-tail) (r (cdr todo))
(if res-head
(setf (cdr res-tail) (list (car todo))
res-tail (cdr res-tail))
(setq res-head (list (car todo))
res-tail res-head))
(values res-head res-tail))
(values nil nil))))
(values (r l))))
PS. Your specific error is incomprehensible, please contact your vendor.

Idiomatic way to group a sorted list of integers?

I have a sorted list of integers, (1 2 4 5 6 6 7 8 10 10 10). I want to group them all, so that I get ((1) (2) (4) (5) (6 6) (7) (8) (10 10 10)).
So far I have this, which works:
(let ((current-group (list)) (groups (list)))
(dolist (n *sorted*)
(when (and (not (null current-group)) (not (eql (first current-group) n)))
(push current-group groups)
(setf current-group (list)))
(push n current-group))
(push current-group groups)
(nreverse groups))
But I'm sure there must be a much more LISPy way to do this. Any ideas?
Not that bad. I would write it this way:
(defun group (list)
(flet ((take-same (item)
(loop while (and list (eql (first list) item))
collect (pop list))))
(loop while list
collect (take-same (first list)))))
CL-USER 1 > (group '(1 2 4 5 6 6 7 8 10 10 10))
((1) (2) (4) (5) (6 6) (7) (8) (10 10 10))
There's already an accepted answer, but I think it's worth looking at another way of decomposing this problem, although the approach here is essentially the same). First, let's define cut that takes a list and a predicate, and returns the prefix and suffix of the list, where the suffix begins with the first element of the list that satisfies the predicate, and the prefix is everything before that that didn't:
(defun cut (list predicate)
"Returns two values: the prefix of the list
containing elements that do no satisfy predicate,
and the suffix beginning with an element that
satisfies predicate."
(do ((tail list (rest tail))
(prefix '() (list* (first tail) prefix)))
((or (funcall predicate (first tail))
(endp tail))
(values (nreverse prefix) tail))))
(cut '(1 1 1 2 2 3 3 4 5) 'evenp)
;=> (1 1 1) (2 2 3 3 4 5)
(let ((l '(1 1 2 3 4 4 3)))
(cut l (lambda (x) (not (eql x (first l))))))
;=> (1 1), (2 3 4 4 3)
Then, using cut, we can move down the an input list taking prefixes and suffixes with a predicate that's checking whether an element is not eql to the first element of the list. That is, beginning with (1 1 1 2 3 3) you'd cut with the predicate checking for "not eql to 1", to get (1 1 1) and (2 3 3). You'd add the first to the list of groups, and the second becomes the new tail.
(defun group (list)
(do ((group '()) ; group's initial value doesn't get used
(results '() (list* group results))) ; empty, but add a group at each iteration
((endp list) (nreverse results)) ; return (reversed) results when list is gone
(multiple-value-setq (group list) ; update group and list with the prefix
(cut list ; and suffix from cutting list on the
(lambda (x) ; predicate "not eql to (first list)".
(not (eql x (first list))))))))
(group '(1 1 2 3 3 3))
;=> ((1 1) (2) (3 3 3))
On implementing cut
I tried to make that cut relatively efficient, insofar as it only makes one pass through the list. Since member returns the entire tail of the list that begins with the found element, you can actually use member with :test-not to get the tail that you want:
(let ((list '(1 1 1 2 2 3)))
(member (first list) list :test-not 'eql))
;=> (2 2 3)
Then, you can use ldiff to return the prefix that comes before that tail:
(let* ((list '(1 1 1 2 2 3))
(tail (member (first list) list :test-not 'eql)))
(ldiff list tail))
;=> (1 1 1)
It's a simple matter, then, to combine the approaches and to return the tail and the prefix as multiples values. This gives a version of cut that takes only the list as an argument, and might be easier to understand (but it's a bit less efficient).
(defun cut (list)
(let ((tail (member (first list) list :test-not 'eql)))
(values (ldiff list tail) tail)))
(cut '(1 1 2 2 2 3 3 3))
;=> (1 1), (2 2 2 3 3)
I like to use reduce:
(defun group (lst)
(nreverse
(reduce (lambda (r e) (if (and (not (null r)) (eql e (caar r)))
(cons (cons e (car r)) (cdr r))
(cons (list e) r)))
lst
:initial-value nil)))
or using push:
(defun group (lst)
(nreverse
(reduce (lambda (r e)
(cond
((and (not (null r)) (eql e (caar r))) (push e (car r)) r)
(t (push (list e) r))))
lst
:initial-value nil)))

LISP &rest issue

So I'm new to LISP, and I'm playing with a couple of basic sum functions.
(defun suma (&rest L)
(cond
((null L) 0)
(T (+ (CAR L) (EVAL (CONS 'suma (CDR L)))))
))
(defun suma2 (&rest L)
(cond
((null L) 0)
(T (+ (car L) (suma2 (cdr L))))
))
The first function works just fine. The second function gives this error: SB-KERNEL::CONTROL-STACK-EXHAUSTED.
My question is: why is the first function ok and the second is not when they are essentially doing the same thing?
If you call, say, (suma2 1 2 3), L will be the list (1 2 3). You will then call (suma2 (cdr L)), i.e. (suma2 '(2 3)). In that invocation L will be the list ((2 3)), i.e. a list containing a single element: the list (2 3). Now it will call (suma2 (cdr L)) again and this time (cdr L) is the empty list, so in the next invocation L is a list containing the empty list. Since that's still a list containing one element, it will again recurse and again and again. The case where L is empty will never be reached because L will always be a list containing exactly one element: the result of (cdr L).
So you should either change your suma2 function to accept a list instead of a variable number of arguments (and then call it as (suma2 (list 1 2 3)) or (suma2 '(1 2 3)) instead of (suma2 1 2 3)) or use apply to call suma2 with the contents of the list as its arguments instead of the list itself.
Your function call in the second function (-> suma2) is wrong.
You expect your function to be called like this:
(suma2 1 2 3 4)
But the first recursive call is equivalent to this:
(suma2 '(2 3 4))
You pass a list, where individual elements are expected. See the documentation for APPLY.