&rest in common lisp - function

I am confused as to what &rest does in common lisp.
This could be an example to represent what I mean :
(defmacro switch (value &rest pairs)
....
)
What exactly does the &rest and pairs mean?

The last parameter in a function (or macro) definition can be preceded by &rest. In this case, when the function (or the macro) is called, all the arguments not bound to the previous parameters are collected into a list which is bound to that last parameter. This is a way of providing an unspecified number of arguments to a function or a macro.
For instance:
CL-USER> (defun f (a &rest b)
(list a (mapcar #'1+ b)))
F
CL-USER> (f 1 2 3 4 5)
(1 (3 4 5 6))
CL-USER> (f 1)
(1 NIL)
CL-USER> (f 1 2 3)
(1 (3 4))
CL-USER> (defmacro m (f g &rest pairs)
(let ((operations (mapcar (lambda (pair) (list g (first pair) (second pair))) pairs)))
`(,f (list ,#operations))))
M
CL-USER> (macroexpand-1 '(m print + (1 2) (3 4) (5 6)))
(PRINT (LIST (+ 1 2) (+ 3 4) (+ 5 6)))
T
CL-USER> (m print + (1 2) (3 4) (5 6))
(3 7 11)
Note that, if the are no remaining arguments, the list passed to the last parameter is empty.

Related

Common Lisp - Function that builds, from a list of numbers, the list of more, smaller or equal to a given number

I having trouble with this function,
I would like a function which
returns a list of number inferior for a given a number.
What I did so far,
(defun inf (n l)
(cond
((not l) 0)
((>= n (car l))(cons n (inf n(cdr l))))
(cons (car l) (inf n (cdr l))) ))
But it keeps returns
(inf 12 '(12 5 3))
(12 12 10)
Instead of :
(inf 12 '(12 5 3 53 45))
(12 5 3)
What did I miss ?
First of all, the function you posted does not behave the way you claim.
The 1st invocation returns (12 12 12 . 0) (because you return 0 instead of nil in the 1st cond clause)
and the second invocation raises an exception
COND: variable CONS has no value
because you got cond syntax wrong.
Second, the question summary, question text, and the attempted
implementation, specify three different problems.
Here is a fix for your code (I replaced
car and cdr with
first and
rest for pedagogical reasons):
(defun inf (n l)
(cond
((not l) ()) ; return empty list
((>= n (first l))
(cons n (inf n (rest l))))
(t
(cons (first l) (inf n (rest l))))))
If this is, in fact, what you want, you can implement in a more
idiomatic way:
(defun inf-1 (n l)
(and l (cons (max n (first l)) (inf-1 n (rest l)))))
or even
(defun inf-2 (n l)
(mapcar (lambda (x) (max n x)) l))
If you actually want the list of numbers less than the given one, you
can use remove:
(remove 12 '(12 5 3 100) :test #'<=)
==> (5 3)
A not-so-obvious way to solve the same problem using Common Lisp's existing functions is to pass a comparison operator to REMOVE.
(remove 10 '(0 3 5 11 22 10 22 3 2) :test #'<)
The above removes all elements "equal" to 10 according to #'<, which are thus all elements u such that (< 10 u) holds. In other words, all elements strictly above 10:
(0 3 5 10 3 2)
It turns out that there is an example of this in the section linked above:
(remove 3 '(1 2 4 1 3 4 5) :test #'>) => (4 3 4 5)
Edit: since this is now the accepted answer, note also that this approach is probably hard to read, be careful when using it (add a comment, etc.).

Calling lambda function directly

(define a1 (list 1 2 3 4))
(define a2 (list + - * /))
(define a3 (list 5 6 7 8))
(map (lambda (x y z) (y x z))
a1 a2 a3)
How do I call this lambda function directly without using map?
All it does is switching y and x, so that (1 + 5) becomes (+ 1 5)
You can write you map expression without switching the arguments:
(map (lambda (x y z) (x y z)) a2 a1 a3) ; ==> (6 -4 21 1/2)
Notice I have just switched the order of the arguments to map.
You can call a lambda by wrapping it in parenthesis and adding arguments.. eg.
((lambda (op1 proc op2) (proc op1 op2)) + 2 3) ; ==> 5
The map function is just a way of doing that with every element of the different lists. You can get the same result without using lambda if you know the length of the lists:
(list ((car a2) (car a1) (car a3))
((cadr a2) (cadr a1) (cadr a3))
((caddr a2) (caddr a1) (caddr a3))
((cadddr a2) (cadddr a1) (cadddr a3))) ; ==> (6 -4 21 1/2)
Since every element of a2 is a procedure wrapping it and arguments in parenthesis applies the procedure.
A lambda form (lambda (arg ...) body ...) gets evaluated and turns into a procedure object. When you define named procedure the same happens but the name gets bound to that procedure object. In fact. there is not difference between these 3 versions:
;; version 1 using syntactic sugar define for procedures
(define (test x) (* x x))
(test 10) ;==> 100
;; version 2 defineing a variable to a procedure
(define test (lambda (x) (* x x)))
(test 10) ;==> 100
;; version 3 using the procdure directly
((lambda (x) (* x x)) 10) ; ==> 100
As you probably know, to call a function in Scheme you write (f args), where f is the function and args is the list of arguments. This isn't any different whether f is a named function or a lambda. So to call your lambda function directly, you'd write:
;( -----------f------------ args- )
( (lambda (x y z) (y x z)) 1 + 2 )
Of course that's just a rather convoluted way of writing (+ 1 2), but there you go.

Multiplying 2 lists in Lisp

I have a function that takes 2 lists as input and I would like to make it so that everything in the first list, is multiplied with everything in the second list, and then the sum is calculated.
Here's my function so far:
(defun multiply(a b)
(if (eq a nil)
0
(progn
(* (car a) (car b))
(multiply (car a) (cdr b)))
))
Currently all I'm trying to get it to do is take the first number from the first list, and multiply one by with everything in the second list. However I get this error from when the function is re-called within the function:
(This is what I inputted, '(1 2 3) and '(4 5 6))
The value 1 is not of type list.
(MULTIPLY 1 '(5 6))
Any help would be much appreciated.
Is loop acceptable?
Case 1
If the result should be 90 as in
(+ (* 1 4) (* 1 5) (* 1 6) (* 2 4) (* 2 5) (* 2 6) (* 3 4) (* 3 5) (* 3 6))
then you could do
(defun multiply (a b)
(loop for i in a
sum (loop for j in b
sum (* i j))))
Case 2
If the result is supposed to be 32 as in
(+ (* 1 4) (* 2 5) (* 3 6))
then it would be
(defun multiply (a b)
(loop
for i in a
for j in b
sum (* i j)))
If you want to multiply two lists per element, you should just be able to use mapcar:
(mapcar #'* '(3 4 5) '(4 5 6))
As to the error in your existing function, this line should be:
...
(multiply (cdr a) (cdr b)))
...
What you describe sounds like the dot product:
(defun dot (l1 l2)
(reduce #'+ (mapcar #'* l1 l2)))
The above solution is nice because it is purely functional, but, alas, it creates an unnecessary intermediate list. Of course, a Sufficiently Smart Compiler should be able to eliminate that, but, practically speaking, you are better off using loop:
(defun dot (l1 l2)
(loop for x in l1 and y in l2 sum (* x y)))
Note also that using lists to represent mathematical vectors is not a very good idea, use vectors instead.
I would modify multiply as
(defun multiply(a b)
(if (eq a nil)
0
(+
(* (car a) (car b))
(multiply (cdr a) (cdr b)))))
When you call
(multiply '(1 2 3) '(4 5 6))
it will return the sum
32
(define (*2Ls L1 L2)
(apply map * (list L1 L2)))

Scheme recursive unzip function for more than one list

I need help finishing up an unzip function which takes a zipped list and returns a list of two lists. The result I want is as follows...
(unzip '((a b) (1 2)))
'((a 1) (b 2))
(unzip '((a 1) (b 2) (c 3)))
'((a b c) (1 2 3))
(unzip '(unzip '()))
'(() ())
I can get my code to work for the null case and with a list containing two lists, but I'm having a hard time figuring out how to make it recursive and work for more than 2 lists such as the second example.
(define (unzip l)
(if (null? l)
'(() ())
(map list (car l) (car (cdr l)))))
This will work fine for an empty list or two lists, but I have a hard time setting up the recursive part to work with three or possibly more lists.
This is a pretty standard operation, it's equivalent to finding the transpose of a list of lists. It's usually implemented like this:
(define (unzip lst)
(apply map list lst))
It'll work for the first two examples. The third, I believe is ill-defined, but if you want to make it work for that weird case, I'll leave that as an exercise ;)
Notice that if you unzip an unzipped list you get back the original input ... meaning that unzip is also zip!
(unzip '((a b) (1 2) (x y)))
=> '((a 1 x) (b 2 y))
(unzip '((a 1 x) (b 2 y)))
=> '((a b) (1 2) (x y))
(apply map list '((a 1) (b 2) (c 3) (d 4) (e 5)))
;Value 16: ((a b c d e) (1 2 3 4 5))
this does it. BTW the same trick does it for zipping as well, provided all the lists are of the same length:
(apply map list (list '(a b c d e) '(1 2 3 4 5)))
;Value 17: ((a 1) (b 2) (c 3) (d 4) (e 5))
Are you aware that in Scheme a function can return multiple values?
(define (unzip list)
(values (map car list)
(map cadr list)))
and then use it like this:
(let-values ([(z1 z2) (unzip '((a 1) (b 2)))])
;; Use z1 and z2
...)

Using abstract list functions to iterate over a list of functions in Scheme

How can I write a function max-list-function that consumes a list of functions, then produces a function f such that for every x, (f x) produces the maximum value of all the functions g in the list of functions?
For example (max-list-function (lambda (n) (+ n 4)) (lambda (n) (- 15 n))))
produces a function such that (f 2) returns 13 and (f 10) returns 14.
This is to be done with abstract list functions (filter, foldr, map, ...) without recursion.
Try this:
(define (max-list-function flist)
(lambda (n)
(foldr max -inf.0
(map (lambda (f) (f n))
flist))))
Use it like this:
(define f (max-list-function
(list (lambda (n) (+ n 4)) (lambda (n) (- 15 n)))))
(f 2)
> 13.0
(f 10)
> 14.0