#0: BIBLIOGRAPHY: ---------------------------------------------------------- * Conrad Barski, Land of LISP, No Starch Press, 2010 * Practical Common Lisp: Peter Seibel 2005 Apress * ANSI Common Lisp: Paul Graham 1995 Prentice Hall You will use CLISP #1: Introduce LISP -------------------------------------------------------- Lisp is the second-oldest high-level programming language after Fortran; It invented by John McCarthy in 1958 while he was at the Massachusetts Institute of Technology (MIT). Today, the most widely known general-purpose Lisp dialects are Common Lisp and Scheme. Lisp is particularly suitable for Artificial Intelligence programs, as it processes symbolic information effectively. In this class, we will use CLISP. #2 Introduce POLISH Notation --------------------------------------------- * In Lisp, expressions start with an operator (a ) followed by its arguments. This is called the PREFIX notation or POLISH notation. * The basic numeric operations in LISP are +, -, *, and / * LISP represents a function call f(x) as (f x) * LISP expressions are case-insensitive, (F X) or (f x) are the same. * In LISP, only three types of elements are constants and always return their own value - numbers; - t -> true boolean operator - nil -> false boolean operator / empty list -> EXERCISE 1 ---------------------------------------- ; 5 + 76 - 8 = 73 (- (+ 5 76) 8)) ; 17 - 45 * 23 = -1018 (- 17 (* 45 23))) ; (17 - 45) * 23 = -644 (* (- 17 45) 23) ; 23 - 57 *34 / 687 = 20.179039 (- 23 (/ (* 57 34) 687.0)) ; 15 * 7 + 48 / 5 * 10 + 8 / 4 = 203 (+ (* 15 7) (* (/ 48 5) 10) (/ 8 4)) -------------------------------------------------------- # BOOLEAN OPERATORS * AND -> only TRUE when ALL arguments are TRUE * OR -> only FALSE when ALL arguments are FALSE * NOT -> converts T -> NIL / NIL -> T -> EXERCISE 1.2. -------------------------------------------- (and (= 3 4) (< 3 4) (> 3 4)) ; NIL (or (= 3 4) (< 3 4) (> 3 4)) ; T ; RETURNS THE OUTCOME OF THE LAST EXPRESSION (and (+ 3 4) (- 3 4) (* 3 4)) ; 12 ; RETURNS THE OUTCOME OF THE FIRST EXPRESSION (or (+ 3 4) (- 3 4) (* 3 4)) ; 7 ------------------------------------------------------------- LISP programs are made up of three basic building blocks: - ATOM: a number or string of contigous characters. It includes numbers and special characters. Ex: hello *hello* Catarina Block#221 12345678 abc123 - LIST: s a sequence of atoms and/or other lists enclosed in parentheses. Ex: ( i am a list) ( ) (a ( a b c) d e fgh) (dom seg ter qua qui sex sab) - STRING: is a group of characters enclosed in double quotation marks. Ex: "I am a string" "Please enter the following details :" "a ba c d efg #$%^&!" "Welcome to 'Artificial Intelligence'" __________________________________________________________________________________ # Comments There are two types of comments: [1] The semicolon symbol (;) is used for indicating a comment line. [2] The semicolon symbol #| (...) |# is used for indicating a comment line. Ex: #| check who will be the next player if it was played an X, then... |# (if (eql (estado-proximo estado) 'X) (setf (estado-proximo novo-estado) 'O) ; the next player will play O' (setf (estado-proximo novo-estado) 'X)) ; the next player will play X' ------------------------------------------------------------------------------------ # VARIABLES * GLOABAL VARIABLES: Global variables have permanent values throughout the LISP system and remain in effect until a new value is specified. * DEFFVAR: assigns a value to a variable ONCE > (defvar x 234) > x 234 > (defvar x 4) > x 234 You can change the value of the variable using SETF > (setf x 4) > x 4 * DEFPARAMETER: ALWAYS assigns a value to the variable > (defparameter y 23) > y 23 > (defparameter y 4) > y 4 You can change the value of the variable using SETF > (setf y 25) > y 25 * LOCAL VARIABLES: Local variables are defined within a given procedure. Local variables are accessible only within the respective function. (let ((x 'a) (y 'b) (z 'c)) (setf x 1) (setf y 2) (setf z 3)) ---------------------------------------------------------------------------------------------- # PRINTING (print "para fazer escape pomos um \"") (print "ola") (prin1 "ola") (princ "ola") (setf var1 3) (format t "~%VAR1 = ~a~%" var1) # COMPARISON ---------------------------------------------------------------------------------- * (eq x y) is true if and only if x and y are the same identical object.~%" * The eql predicate is true if its arguments are eq, or if they are numbers of the same type with the same value, or if they are character objects that represent the same character * The EQUAL predicate is true if its arguments are structurally similar (isomorphic) objects. A rough rule of thumb is that two objects are equal if and only if their printed representations are the same. * Two objects are equalp if: [1] they are equal [2] if they are characters and satisfy char-equal, which ignores alphabetic case and certain other attributes of characters [3] if they are numbers and have the same numerical value, even if they are of different types or if they have components that are all equalp (eq 'fooo 'FoOo) ; T (setf a 2) (setf b 2) (eq a b) ; T (eq 'a 'b) (eq 2 4) ; nil (equal a b) ; T (equal "asd" "AsD") ; NIL (equalp "asd" "AsD") ;T # CONDITIONAL STATEMENTS ------------------------------------------------------------------------- * In LISP, conditional statements can be: (IF [condition] [outcome] [otherwise / else outcome] ) (COND ( ( [condition1] ) [outcome1] ) ( ( [condition2] ) [outcome2] ) ... ( [conditionN] ) [outcomeN] ) (T [default outcome])) (when [condition] -> same as if / then condition [outcome] ) (unless [condition] -> same as if / else condition [outcome] ) Ex: (if (= (+ 3 4) 7) 'COOL 'NOT_COOL) (cond ((= (+ 3 4) 7) 'SEVEN) ((= (+ 3 5) 8) 'EIGHT) ('OTHERWISE 'DO_NOT_KNOW)) (when (= (+ 3 4) 7) 'COOL) (unless (= (+ 3 10) 7) 'NOT_COOL) ______________________________________________________________________________________________ # FUNCTIONS * In Lisp, a function has the form: (DEFUN [func_name] ( [arg1] [arg2] [...] [argn]) [body] ) -> EXERCISE 1.3. -------------------------------------------- (defun my_max (a b) "funcao max que recebe dois numeros e devolve o maior deles" (if (>= a b) a b)) -> EXERCISE 1.4. -------------------------------------------- ; using If statement (defun max3_if ( a b c ) "funcao max3 que recebe tres numeros e devolve o maior deles, usando IF" (if (and (>= a b) (>= a c)) a (if (and (>= b a) (>= b c)) b c))) ; using COND statement (defun max3_cond ( a b c ) "funcao max3 que recebe tres numeros e devolve o maior deles, usando COND" (cond ( (and (>= a b) (>= a c)) a) ( (and (>= b a) (>= b c)) b) (T c))) ; using My_Max function (defun max3_max ( a b c ) "funcao max3 que recebe tres numeros e devolve o maior deles, usando MY_MAX" (my_max (my_max a b) c)) # RECURSIVIDADE -------------------------------------------------------------------- * Uma função que é dita recursiva é aquela que invoca ela mesma. * A recursividade é executada numa chamada completamente independente da mesma função. * É preciso um cuidado especial para não cairmos em um looping infinito. * Por isso, precisamos de uma CONDIÇÂO de PARAGEM * baseiam-se numa abordagem declarativa. -> EXERCISE 1.5. ------------------------------------------------------------------ (defun soma ( a b ) "funcao soma que recebe dois numeros inteiros nao negativos e retorna a sua soma. Apenas pode usar recursao, a forma especial if e as funções 1+, 1- e zerop." (if (zerop a) b (soma (1- a) (1+ b)))) # CICLOS --------------------------------------------------------------------------- ; http://cl-cookbook.sourceforge.net/loop.html (loop for x in '(a b c d e) do (print x) ) (loop for x in '(a b c d e) for y in '(1 2 3 4 5) collect (list x y) ) (loop for x in '(a b c d e) for y from 1 if (> y 1) do (format t ", ~A" x) else do (format t "~A" x) ) (dolist (x '(a b c d)) (prin1 x) (princ " ")) # ITERATIVIDADE * função que utiliza funções de ciclo para repetir os comandos da função. * dependem de uma condição ser verdadeira ou falsa para iniciar ou interromper o ciclo. * baseiam-se numa abordagem imperativa. -> EXERCISE 1.5. (versão iterativa) ------------------------------------------------------------------ (defun soma_iter ( a b ) (let ((res b)) (loop for i from 1 to a do (incf res 1)) res)) -> EXERCISE 1.6. ------------------------------------------------------------------ (defun potencia_rec ( num exp ) "funcao potencia que recebe dois numeros e calcula o valor de elevar o primeiro (a base) ao segundo (o expoente). Assuma que o expoente e sempre um inteiro >= 0" (if (zerop exp) 1 (* num (potencia_rec num (- exp 1))))) (defun potencia_iter_loop ( num exp ) "funcao potencia que recebe dois numeros e calcula o valor de elevar o primeiro (a base) ao segundo (o expoente). Assuma que o expoente e sempre um inteiro >= 0" (let ((result 1)) (loop for x from 1 to exp do (setf result (* result num))) result)) (defun potencia_iter_dotimes ( num exp ) "funcao potencia que recebe dois numeros e calcula o valor de elevar o primeiro (a base) ao segundo (o expoente). Assuma que o expoente e sempre um inteiro >= 0" (let ((result 1)) (dotimes (x exp) (setf result (* result num))) result)) -> EXERCISE 1.8. ------------------------------------------------------------------ (defun soma_iter-1 ( my_list ) "função soma-1 que recebe uma lista de números e retorna uma lista de números cujos elementos são os elementos da lista argumento adicionados de uma unidade." (let ((res () )) (loop for x in my_list do (setf res (append res (list (+ x 1))))) res)) (defun soma_rec-1 ( my_list ) "função soma-1 que recebe uma lista de números e retorna uma lista de números cujos elementos são os elementos da lista argumento adicionados de uma unidade." (if (null my_list) () (cons (+ 1 (first my_list)) (soma_rec-1 (rest my_list))))) # RUNNING PROGRAMS in LISP ---------------------------------------------------------- LISP programs run either on an interpreter or as compiled code. Interpreted: > (load "my_file.lisp") Compiled (generated two files: my_file.fas & my_file.lib) > (compile-file "my_file.lisp") > (load "my_file")