Lisp EN -- Laboratory 5 -- 2006-2007 -- info.uvt.ro

Important! These pages are somehow outdated and it is recommended to consult the newer version at Functional programming -- 2008-2009 -- info.uvt.ro (by Ciprian Crăciun).

Lisp EN -- 2006-2007 -- info.uvt.ro


Evaluation functions

edit

As we know Lisp treats code and data the same. The code is nothing more than a data structure which has a well specified form (the form is the syntax). The interpretor receives a data structure and tries to execute it step by step.

The same functionality is available to the user through the function eval.

(eval <statement>) => <evaluation>
(eval '(+ 1 2)) => 3
(do
    ((in (read) (read)))
    ((cond
        ((eq in 'q) t)
        (t (prin1 (eval in)) (princ #\nl) nil)
     ) nil))
(defun read-eval-print ()
    (princ ">> ")
    (prin1 (eval (read)))
    (princ #\nl)
    (read-eval-print))
(read-eval-print)


funcall is used to programatically evaluate a function. It is usually used when we know in advance the number of arguments for the given function.

(funcall <function> <argument-1> ... <argument-n>) => <evaluation>
(funcall #'+ 1 2 3)
(funcall #'print "abc")


apply, like funcall is used to evaluate a function, but it is used when we don't know in advance the number of arguments for the given function.

(apply <function> <argument-list>) => <evaluation>
(apply #'+ '(1 2 3 4 5)) => 15
(apply #'cons '(a b)) => (a . b)
(defun max-list (l)
    (apply #'max l))

(max-list '(1 2 3 5 4 3 2 1)) => 5
(defun sum-list (l)
    (apply #'+ l))

(sum-list '(1 2 3 4 5)) => 15


mapcar function family

edit

Many times we want to apply a specific function to all the elements in a given list, and for this reason mapcar function family was built.

mapcar takes as arguments a function and a set of lists. The result is obtained by applying the given function to parameters obtained from each list. For example:

(mapcar #'+ '(1 2 3) '(5 6 7)) => (6 8 10)
(mapcar <function> <list-1> ... <list-n>)
=> ({<function> applied on arguments: first element in <list-1>, ..., first element in <list-n>}
    {<function> applied on arguments: second element in <list-1>, ..., second element in <list-n>)
    ...)
(mapcar #'oddp '(1 2 3 4 5)) => (t nil t nil t)
(mapcar #'cons '(1 2 3 4 5) '(a b c d e)) => ((1 . a) (2 . b) (3 . c) (4 . d) (5 . e))

maplist has the same syntax, but instead of using as arguments to the given function the n-th element of the lists, it uses the remaining n-th pairs in the list.

(maplist #'length '(a b c d e)) => (5 4 3 2 1)
(maplist #'cdr '(a b c d e)) => ((b c d e) (c d e) (d e) (e) ())


Lambda

edit

lambda is a form used to define anonymous functions. It has the same syntax as defun, except that lambda doesn't name the function but returns it.

(lambda (<argument-1> ... <argument-n> <statement-1> ... <statement-n>) => <statement-n's value when executed>
(mapcar (lambda (x) (- 0 x)) '(1 2 3 4 5))


Conditional list processing functions

edit
(count-if #'oddp '(1 2 3 4 5 6 7)) => 4
(count-if #'atom '(1 2 3 (4 5 6) 7 8)) => 5

(remove-if #'oddp '(1 2 3 4 5 6 7)) => (2 4 6)
(apply #'max (remove-if-not #'numberp '(1 2 a b c (100 200) 3 4 d e f))) => 4

(find-if #'minusp '(1 2 3 4 5 6)) => nil
(find-if #'plusp '(1 2 0 2 1)) => 1

(substitute-if 0 #'oddp '(1 2 4 1 3 4 5)) => (0 2 4 0 0 4 0)


assoc function family

edit
(assoc <key> <record-list>) => <record>
(assoc-if <key> <record-list>) => <record>
(rassoc <key> <record-list>) => <record>
(rassoc-if <key> <record-list>) => <record>
(setq db '((1 . a) (2 . b) (3 . c)))
(assoc 1 db) => (1 . a)
(assoc 0 db) => nil
(assoc-if #'evenp db) => (2 . b)
(assoc-if #'oddp db) => (1 . b)
(rassoc 'a db) => (1 . a)
(rassoc 'z db) => nil


Assignment 5

edit

This assignment is due next Wednesday (2007-04-04) at 24:00, and should be sent by email.

When you send the email please include in the subject [LISP-EN-2] First_name Last_name for the second year and [LISP-EN-3] First_name Last_name for the third year. Please paste the code inside the email, DO NOT ATTACH any files.

The assignment for next week is:

  • to implement 3 functions using 3 different functions from the mapcar family;
  • to re-implement 3 different functions presented in the Conditional list processing functions above.

You will have to provide examples for all the implemented functions and to use lambda as the argument function. For example:

(defun my-count-if (l) ...)

(my-count-if (lambda (e) (numberp e)) '(1 2 3 4 a b c)) => 4


Ciprian Dorin Craciun

2007-03-28

ccraciun@info.uvt.ro