#-------------------------------------------------------------------------- # Gli elementi primi del LISP: ATOMI e LISTE #-------------------------------------------------------------------------- # sono atomi: i numeri > 1 1 # la costante booleane t (= true) > t T # la costante lista NIL (= lista vuota) serve per il falso: > nil NIL # le liste sono denotate con parentesi tonde... ecco la lista vuota: > () NIL # sono atomi gli identificatori # ma attenzione, vanno definiti! >f *** - EVAL: variable F has no value # per definire un identificatore... > (setq f 3) 3 > f 3 # Le liste vengono interpretate come segue: # il primo elemento e' una funzione, i restanti sono gli argomenti > (+ 1 2) 3 # che vengono valutati PRIMA di essere passati alla funzione: > (+ f 2) 5 # le liste possono essere ANNIDATE. Se un argomento e' una lista, prima viene valutato: > (setq g (+ f 2)) 5 >g 5 # OSSERVATE pero': # variabili e funzioni sono DUE MONDI DIVERSI. setq e' una funzione! > setq f 3 *** - EVAL: variable SETQ has no value # il primo elemento di una lista viene valutato come fosse una funzione # da applicare agli argomenti nel resto della lista: > (f) *** - EVAL: the function F is undefined # anche le costanti sono un mondo a parte. NON si possono assegnare: > (setq t nil) *** - SETQ: the value of the constant T may not be altered #-------------------------------------------------------------------------- # MANIPOLAZIONE di LISTE #-------------------------------------------------------------------------- # costruzione delle liste: cons >(setq l (cons 1 nil)) (1) > (setq m (cons 2 l)) (2 1) # la testa di una lista e' il CAR (Contents of the Address Register) > (car m) 2 # la coda di una lista e' il CDR (Contents of the Decrement Register) # osservate che e' una lista! > (cdr m) (1) > (cdr (cdr m)) NIL # ma anche: > (cddr m) NIL > (car (cdr m)) 1 # ma anche: > (cadr m) 1 # piu' prosaicamente, nelle nuove versione di LISP: > (first m) 2 > (rest m) (1) # sono predefinite la funzione append: > (append l m) (1 2 1) # e la funzione LIST per creare una lista indicando i suoi elementi: > (list 1 2 3) (1 2 3) # Ricordate infatti che altrimenti la lista viene letta nella forma: # (fun-name arg1 ... argn) > (1 2 3) *** - EVAL: 1 is not a function name #-------------------------------------------------------------------------- # Blocco della valutazione: QUOTE #-------------------------------------------------------------------------- # anche le liste interne vengono valutate: > (car (1 2)) *** - EVAL: 1 is not a function name # il quote blocca la valutazione: > (car (quote (1 2))) 1 # visto il largo uso, il quote viene abbreviato con ' > (car '(1 2)) 1 > '(1 2) (1 2) > (append '(2 3) '(1 2)) (2 3 1 2) # osservate che un quote esterno blocca la valutazione # anche delle liste interne > '(f (f g)) (F (F G)) # Possiamo quotare ANCHE i PROGRAMMI! In fondo sono liste essi stessi! > ' (setq a 7) (SETQ A 7) # osservate anche # (length funzione predefinita che da la lunghezza di una lista): > (length (append l l)) 2 > (length '(append l l)) 3 #-------------------------------------------------------------------------- # PREDICATI UTILI: # atom, listp, symbolp, numberp #-------------------------------------------------------------------------- # l e' una lista... > (atom l) NIL # ma 'l ? > (atom 'l) T > (atom f) T > (atom 1) T # e la lista vuota?? > (atom nil) T # come sappiamo e' anche una lista... > (listp nil) T # Ovviamente: > (numberp 1) T # ma anche: (gli argomenti vengono valutati PRIMA dell'applicazione!) > (numberp f) T #-------------------------------------------------------------------------- # PRIMITIVE *NON* FUNZIONALI: setf, rplaca, #-------------------------------------------------------------------------- # ricordiamo che setq crea associazioni nomi-valori: > (setq n (cons '(1 2) l)) ((1 2) 1) # l rimane invariata > l (1) # cambiano l NON modifico n! > (setq l nil) NIL > n ((1 2) 1) # possiamo pero' produrre side-effects su n con SETF: > (setf (car n) 1) 1 > n (1 1) > (setf (cdr n) '(1 2)) (1 2) > n (1 1 2) # per motivi storici e' giusto ricordare RPLACA e RPLACD: > (rplaca n 8) (8 1 2) # facendo degli errori... ci si ricorda che si implementa tutto con coppie... > (rplaca 8 n) *** - RPLACA: 8 is not a pair > (rplacd n 8) (8 . 8) # che significa il punto??? # la coda puo' NON essere una lista! > (cdr n) 8 > (rplacd n '(8)) (8 8) #-------------------------------------------------------------------------- # DEFINIZIONE di FUNZIONI: DEFUN e LAMBDA #-------------------------------------------------------------------------- # si possono definire funzioni via lambda notazione (analoga a fn x => ... di ML) > (setq product (lambda (x y)(* x y))) # # pero' product in questo caso e' il nome di una variabile e non di una # funzione! > (product 3 4) *** - EVAL: the function PRODUCT is undefined # esiste pero' un modo esplicito per eseguire l'applicazione > (apply product '(3 4)) 12 # o piu' tipicamente attraverso defun: > (defun twice (x) (+ x x)) TWICE # ora twice e' il nome di una funzione: > (twice 2) 4 # posso ricorrere all'apply quotando twice: > (apply 'twice '(2)) 4 # Funzionali... le cose non sono cosi' semplici... > (defun fdi3 (f) (apply f 3)) FDI3 > (fdi3 'twice) 6 > (defun selfApp (f) (apply f `(,(apply f '(3))))) SELFAPP > (selfApp 'twice) 12 > (defun selfApp (f x) (funcall f (funcall f x))) SELFAPP > (selfApp 'twice 3) 12 > (defun compose (f g x)(funcall f (funcall g x))) COMPOSE > (compose 'twice 'twice 3) 12 # le definizioni possono essere ricorsive: ecco il map: # (esiste la funzione pedefinita map) >(defun myMap (f l) (if (null l) nil (cons (funcall f (car l)) (myMap f (cdr l))) ) ) MYMAP > (myMap 'twice '(1 2 3)) (2 4 6) #-------------------------------------------------------------------------- # ESPRESSIONI CONDIZIONALI: if, cond; PREDICATI: eq, eql #-------------------------------------------------------------------------- > (if t 3 2) 3 > (if () 3 2) 2 > (LAMBDA (X) (+ X X)) # > ((LAMBDA (X) (+ X X)) 4) 8 > (defun double (x) (+ x x)) DOUBLE > (double 9) 18 > (setq c 'a) A > (setq a '(b c)) (B C) > (a) *** - EVAL: the function A is undefined > a (B C) > (eval a) *** - EVAL: the function B is undefined > c A > (eval c) (B C) 41. Break [42]> (set a 5) *** - SYSTEM::SET-SYMBOL-VALUE: # is not a symbol 42. Break [43]> (set d 5) *** - EVAL: variable D has no value 43. Break [44]> (set (quote d) 5) 5 43. Break [44]> d 5 43. Break [44]> (d) *** - EVAL: the function D is undefined > (if t 3 2) 3