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

From Wikiversity
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


Variables, parameters and constants[edit]

Variables[edit]

  • defvar
    • It defines a variable with the given name.
    • It assigns the variable with the given value, only if the variable was not assigned early.
(defvar <name> [<initial-value> [documentation]])
(defvar var-1 1 "variable 1")
(print var-1) => 1
(defvar var-1 2)
(print var-1) => 1


Parameters[edit]

  • defparameter
    • It defines a variable with the given name.
    • It assigns the variable with the given value, regardless of the variable state (newly defined or old one). Thus it overwrites the old value.
(defparam <name> <initial-value> [documentation])
(defparameter param-1 1 "param-1")
(print param-1) => 1
(defparameter param-1 2)
(print param-1) => 2


Constants[edit]

  • defconstant
    • It defines a constant (in fact a variable) with the given name.
    • It assigns the constant with the given value, regardless of the constant state (just like defparameter) but it this case it issues a warning.
    • As a convention the constants start and end with *.
(defconstant <name> <initial-value> [documentation])
(defconstant const-1 1 "const-1")
(print const-1) => 1 and a warning
(defconstant const-1 2)
(print const-1) => 2
  • constantp
    • It checks if the given symbol is a constant name or if the given argument is considered to be a constant.
(constantp <symbol>)
(constantp 'var-1) => nil
(constantp 'param-1) => nil
(constantp 'const-1) => t
(constantp 1) => t
(constantp var-1) => ?
(constantp param-1) => ?


Assignment[edit]

  • setq
    • It assigns a variable with a given value.
    • It takes an even number of parameters which represent the variable, and the value respectively to assign.
    • It executes sequentially.
(setq <variable> <value>)
(setq <variable-1> <value-1> <variable-2> <value-2> ... <variable-n> <value-n>)
(setq a 1)
a => 1
(setq a 1 b 2)
a => 1
b => 2
(setq a b b a)
a => 2
b => 2
  • psetq
    • It has the same semantic as setq except that when used with multiple pairs, in which case the assignments are performed in parallel.
(psetq <variable-1> <value-1> <variable-2> <value-2> ... <variable-n> <value-n>)
(setq a 1 b 2)
(psetq a b b a)
a => 1
b => 2
  • setf
    • It assigns a value to a place.
    • Like setq it can take multiple pairs of places and values.
    • Like setq it executes the assignments sequentially.
    • A place is in fact an expression accessing a field of a data structure. (See examples section.)
(setf <place> <value>)
(setf <place-1> <value-1> <place-2> <value-2> ... <place-n> <value-n>)
(setq l '(1 2 3))
l => (1 2 3)
(setf (car l) 'a)
l => (a 2 3)
(setf (cdr l) '(5 6))
l => (a 5 6)
(setf (nth 1 l) 'b)
l => (a b 6)
  • psetf
    • It has the same semantic as setf, but, as with psetq, it executes all the assignments in parallel.
  • Circular lists
(setq l '(1 2 3))
(setq (cdddr l) l) => infinite loop

Forms and functions[edit]

  • Forms
    • A form is an executable entity which has the control over the evaluation of it's arguments.
  • Functions
    • A function is an executable entity which has no control over the evaluation of it's arguments, they are evaluated just before calling the function.


Control statements[edit]

  • All the control statements are forms.

Conditional forms[edit]

(if <condition> <then-statement> [else-statement])
(if t 1 2) => 1
(if nil 1 2) => 2
(if t 1) => 1
(if nil 1) => nil
  • when
    • If the condition is true it executes all the statements, and returns the value of the last statement, or nil in case of a false condition)
(when <condition> <statement-1> ... <statement-n>)
(when t (print 1) (print 2)) => 2 and 1, 2 is printed on the console.
(when t 1 2 3) => 3
(when nil 1 2 3) => nil
  • unless
    • It has the same semantic as when except that the statements are executed if the condition is not true.
(unless <condition> <statement-1> ... <statement-n>)
(unless t 1 2 3) => nil
(unless nil 1 2 3) => 3
  • cond
    • This is the Lisp's equivalent of switch in C, or the if ... else-if ... else-if ... else ...
    • It takes a list of cases and searches for a matching case. When it finds one it returns the value of the last statement in it.
    • A case is composed from a condition and some statements.
    • Usually we put a catch all case, with t as a condition.
(cond
    (<condition-1> <statement-1-1> ... <statement-1-n1>)
    (<condition-2> <statement-2-1> ... <statement-2-n2>)
    ...
    (<condition-m> <statement-m-1> ... <statement-m-nm>)
    (t <statement-t-1> ... <statement-t-nt>))
(defun int-test (n)
    (cond
        ((not (integerp n)) "non-integer")
        ((evenp n) "even")
        ((oddp n) "odd")
        (t "error")))
(int-test 1) => "odd"
(int-test 2) => "even"
(int-test "a") => "non-integer"


Code style[edit]

  • Naming conventions
    • Names which are composed from multiple words are written lower case separated by -
int-test
my-sum
    • Constants are pre- and postfixed with *
*max-int*
*e*
  • Indentation
(if short-cond short-then short-else)

(if cond
    then
    else)

(when short-cond short-result)
(unless short-cond short-result)

(when cond
    statement-1
    statement-2)

(unless cond
    statement-1
    statement-2)

(cond
    (cond-1 result-1)
    (cond-2 result-2))


Recursion[edit]

Recursive function cases[edit]

  • Termination (or exit) case
  • Recursive call


Examples[edit]

  • my-expt
(defun my-expt (m n)
    (cond ((zerop n) 1)
        (t (* m (my-expt m (- n 1))))
    ))
  • fibonacci
(defun fibonacci (n)
    (cond ((= n 0) 0)
        ((= n 1) 1)
        (t (+ (fibonacci (- n 1))
              (fibonacci (- n 2))))
    ))
  • count-atoms
(defun count-atoms (l)
    (cond ((null l) 0)
       ((atom l) 1)
       (t (+ (count-atoms (car l))
             (count-atoms (cdr l)))
    ))

Assignment 2[edit]

This assignment is due next Wednesday (2007-03-14) 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.

Write 6 recursive functions:

  • 3 dealing with numbers and arithmetic operations.
  • 3 dealing with list processing.

The functions must be followed by 2 or 3 representative test cases.

These functions must be different than the ones presented in the lab.

Ciprian Dorin Craciun

2007-03-08

ccraciun@info.uvt.ro