Linguaggi di Programmazione Corso di Laurea in Informatica

  • Slides: 79
Download presentation
Linguaggi di Programmazione Corso di Laurea in Informatica Introduzione ai linguaggi funzionali 1

Linguaggi di Programmazione Corso di Laurea in Informatica Introduzione ai linguaggi funzionali 1

I linguaggi imperativi Basati sull’architettura di Von Neumann: – memoria costituita da celle identificate

I linguaggi imperativi Basati sull’architettura di Von Neumann: – memoria costituita da celle identificate da un indirizzo, contenenti dati o istruzioni – unità di controllo e aritmetica – variabili = celle, nome = indirizzo – azione unitaria: istruzione – programma: combinazione di istruzioni Concetto di assegnamento di valori a variabili Ogni valore calcolato deve essere esplicitamente memorizzato, cioè assegnato ad una cella Concetto di iterazione un programma consiste nell’esecuzione iterativa di una sequenza di passi elementari 2

Effetti collaterali Caratteristiche negative dei linguaggi imperativi: gli effetti collaterali • Effetti collaterali –

Effetti collaterali Caratteristiche negative dei linguaggi imperativi: gli effetti collaterali • Effetti collaterali – Modifiche di dati non legati a variabili locali • Sono utilizzati come mezzo di comunicazione tra le diverse unità di un programma: – Variabili globali – Passaggio di parametri per indirizzo • Problemi: – Distinguere tra effetti collaterali desiderati e non desiderati – Leggibilità del programma (l’istruzione di chiamata non rivela quali variabili globali sono coinvolte) – E’ difficile verificare la correttezza di un programma 3

Effetti collaterali • w : = x + f(x, y) + z – f()

Effetti collaterali • w : = x + f(x, y) + z – f() può modificare x e y se sono passati per indirizzo, e z se è globale – si riduce la leggibilità del programma – non ci si può fidare della commutatività dell’addizione! • u : = x + z + f(x, y) + x + z – gli stessi problemi dell’esempio precedente. . . –. . . più l’impossibilità per il compilatore di generare codice ottimizzato valutando una sola volta x + z e f(x, y) 4

Effetti collaterali • Trasparenza referenziale: referenziale il significato del tutto si può determinare dal

Effetti collaterali • Trasparenza referenziale: referenziale il significato del tutto si può determinare dal significato delle parti • Tutti i concetti matematici, in particolare le espressioni, possiedono la proprietà di trasparenza referenziale Esempio: Esempio – nell’espressione matematica f(x) + g(x) si può sostituire f con f’ se producono valori identici – linguaggi imperativi tradizionali: non si può essere certi della sostituzione, né che f(x)+ g(x) = g(x)+ f(x), né che f(x)+f(x) = 2* f(x) 5

I linguaggi funzionali Programmi = funzioni matematiche – concetto base: funzioni primitive – combinazione

I linguaggi funzionali Programmi = funzioni matematiche – concetto base: funzioni primitive – combinazione di funzioni primitive per produrne di più potenti – conservano la trasparenza referenziale della matematica Funzione: Funzione regola per associare gli elementi di un insieme (dominio) a quelli di un altro insieme (codominio) • Una funzione può essere applicata a un elemento del dominio • L’applicazione produce (restituisce) un elemento del codominio Esempio: Esempio quadrato(x) = x*x, dove x è un numero intero, detto argomento, argomento che indica un generico elemento del dominio x è una variabile matematica, non di programma (non ha senso 6 pensare di modificarla!)

Programmazione funzionale: combinazione di funzioni • Consente di creare funzioni complesse a partire da

Programmazione funzionale: combinazione di funzioni • Consente di creare funzioni complesse a partire da funzioni più semplici • Se F è definita come composizione di G e H: F = GºH applicare F equivale ad applicare G al risultato dell’applicazione di H Esempio: Esempio alla_quarta = quadratoºquadrato quindi: quindi alla_quarta(5) = quadrato(5)) 7

Programmazione funzionale: ricorsione Le funzioni nei linguaggi imperativi sono definite in modo procedurale: –

Programmazione funzionale: ricorsione Le funzioni nei linguaggi imperativi sono definite in modo procedurale: – Regola di trasformazione dal dominio al codominio: passi da eseguire in un ordine determinato dalle strutture di controllo In matematica: matematica – In termini di applicazione di altre funzioni (spesso ricorsivamente) Esempio: Esempio – fattoriale(n) = if n = 0 then 1 else n*fattoriale(n-1) Nella programmazione funzionale pura non esiste la possibilità di generare effetti collaterali 8

Programmazione funzionale: caratteristiche • La principale modalità di calcolo è l’applicazione di funzioni •

Programmazione funzionale: caratteristiche • La principale modalità di calcolo è l’applicazione di funzioni • Il calcolo procede valutando espressioni. Non ci sono effetti collaterali. • Le funzioni sono oggetti di prima classe: possono essere componenti di una struttura dati, o costituire l’argomento o il valore di altre funzioni. • I linguaggi funzionali consentono l’uso di funzioni di ordine superiore, cioè funzioni che prendono funzioni come argomento o restituiscono funzioni come valore, in modo assolutamente generale • Nei linguaggi funzionali “puri” non esistono strutture di controllo predefinite per la realizzazione di cicli quali for, while, repeat, ma il principale meccanismo di controllo è 9 la ricorsione.

Il linguaggio Lisp • LISP: acronimo di LISt Processing (elaborazione di liste) • Prima

Il linguaggio Lisp • LISP: acronimo di LISt Processing (elaborazione di liste) • Prima versione: John Mc. Carthy (1960, “Lisp puro”): completamente funzionale – non esistevano variabili – le uniche espressioni ammesse erano la definizione di funzioni e l’applicazione di funzioni • In seguito sono state introdotte caratteristiche non funzionali per aumentare l’efficienza • Oggi è comunque il linguaggio che più si avvicina al modello di linguaggio funzionale • Standard attuale: Common Lisp 10

Il linguaggio Lisp • Il Lisp è un linguaggio interpretato • L’interazione avviene attraverso

Il linguaggio Lisp • Il Lisp è un linguaggio interpretato • L’interazione avviene attraverso una finestra detta listener • L’interprete esegue ripetutamente un ciclo read- eval- print: – legge un’espressione inserita dall’utente (read) – la valuta (eval) – scrive il risultato su schermo (print) 11

Il linguaggio Lisp • Gli unici oggetti (strutture dati) Lisp sono espressioni simboliche: –

Il linguaggio Lisp • Gli unici oggetti (strutture dati) Lisp sono espressioni simboliche: – Atomi – Liste • Atomi – sono rappresentati da stringhe di caratteri – es. : A, John, c 3 po (simboli), 68000, -15, 1. 502, 1. 24 E-3 (numeri) • Liste – sono sequenze ordinate di oggetti, cioè atomi o liste (ricorsivamente) Esempi: Esempi (A), (A John c 3 po 68000), ((A John) c 3 po (68000)), () Anche i programmi Lisp sono espressioni costituite da atomi o liste! Quindi dati e programmi sono rappresentati nello stesso 12 modo.

Il linguaggio Lisp Formalmente le S-espressioni (espressioni simboliche) sono definite come: 13

Il linguaggio Lisp Formalmente le S-espressioni (espressioni simboliche) sono definite come: 13

Il linguaggio Lisp simboli • Usati per dare un nome a variabili, costanti, funzioni

Il linguaggio Lisp simboli • Usati per dare un nome a variabili, costanti, funzioni Sequenze di caratteri che possono includere: numeri, lettere, alcuni caratteri alfanumerici: *-+/@$%^& _ < > ~ (in pratica, ogni identificatore che non e’ un numero e’ un simbolo) – pippo, valore_max, B. 3, 7 -11 … sono simboli – 3. 14, 8, … non sono simboli – Non si fa distinzione tra maiuscole e minuscole • Simboli speciali: – T (“vero”), – NIL (“falso”, ma anche lista vuota) • Predicato: symbolp (restituisce T quando l’argomento dato è 14 un simbolo)

Il linguaggio Lisp numeri • Tipo implicito: number • integer, float • Es. 0.

Il linguaggio Lisp numeri • Tipo implicito: number • integer, float • Es. 0. 5, 3. 1415, 602 E+21 (60221) … • NB: le frazioni, come 2/3, 25/100 … non sono simboli ma vengono trattati come numeri frazionari • Operazioni: – +, -, *, /, sqrt, abs … • Predicati: numberp, integerp …, plusp, zerop …=, >, <, >=, <= … 15

Il linguaggio Lisp le liste Una lista ha una definizione ricorsiva: – () (lista

Il linguaggio Lisp le liste Una lista ha una definizione ricorsiva: – () (lista vuota, o NIL) ricorsione – (l 1 … ln) S-espressioni separate da spazi (li atomo o lista) Esempi: Esempi • (a b c) lista semplice (elementi al primo livello sono atomi) • (( alfa 1) beta (gamma delta (5 127) ro)) e` una lista di liste Liste hanno profondità illimitata orizzontale e verticale • (a ((b b )) (c d (e))) • ((((a))) ((((b) c)))) 16

17

17

Espressioni Lisp Le S-espressioni sono usate per rappresentare: – dati – definizioni di funzioni

Espressioni Lisp Le S-espressioni sono usate per rappresentare: – dati – definizioni di funzioni – applicazioni di funzioni • In Lisp esistono tre tipi di espressioni valide: – atomi – funzioni – espressioni speciali (special form) • Atomi – <nome atomo> • Applicazione di funzioni (<nome funzione> <arg 1> … <argn>) • Espressioni speciali (funzioni speciali) (<nome espressione speciale> <arg 1> … <argn>) 18

Valutazione di espressioni Lisp – Atomi: la valutazione restituisce il valore associato (se non

Valutazione di espressioni Lisp – Atomi: la valutazione restituisce il valore associato (se non esiste: errore) – Liste: Atomo Atomi o liste • Applicazione di funzione (<nome funzione> <arg 1> … <argn>): si passa alla funzione il risultato della valutazione dei suoi argomenti • Espressioni speciali (<nome espressione> <arg 1> … <argn>): si passano all’espressione gli argomenti non valutati La distinzione dipende dal nome (primo atomo della lista) si noti la notazione prefissa! 19

Funzioni predefinite Funzioni matematiche: matematiche +, -, *, /, mod, exp, sqrt, sin, cos

Funzioni predefinite Funzioni matematiche: matematiche +, -, *, /, mod, exp, sqrt, sin, cos Esempio: (+ 1 2) Esempio (* 3 5) (mod 5 2) I piu’ semplici programmi da eseguire 20

Funzioni predefinite per l’elaborazione di liste a) Costruzione di liste: funzione cons: S-Exp List

Funzioni predefinite per l’elaborazione di liste a) Costruzione di liste: funzione cons: S-Exp List (cons <atomo> <lista>) inserisce <atomo> in testa a <lista> Esempi: (cons 1 ()) (1) (cons 1 (cons 2 ())) (1 2) (cons (1 2) (3)) ((1 2) 3) per convenzione significa: ha valore uguale a 21

Funzioni predefinite b) Selezione di elementi: funzioni car (first) e cdr (rest) car: List

Funzioni predefinite b) Selezione di elementi: funzioni car (first) e cdr (rest) car: List S-Exp cdr: List car restituisce il primo elemento di una lista cdr restituisce la lista senza il primo elemento (car = content of address register, cdr =content of decrement register) Esempi: (car (cons 1 (cons 2 ()))) 1 (car (cons 1 (cons 2 ())) (cons 3 (cons 4 ())))) (car ‘((1 2) 3 4)) (1 2) (cdr (cons 1 (cons 2 ())) (cons 3 (cons 4 ())))) (cdr ‘((1 2) 3 4) (3 4) ((x) b (c)) ha come first: (x), come rest: (b (c)) Con cons, car e cdr è possibile eseguire qualsiasi operazione 22 sulle liste (fusione, inserimento, estrazione, ecc. )

Funzioni predicato predefinite Sono funzioni che restituiscono T o NIL (Per rappresentare True e

Funzioni predicato predefinite Sono funzioni che restituiscono T o NIL (Per rappresentare True e False in Lisp si usano gli atomi T e NIL) Predicati di confronto – per i numeri: plusp, zerop …=, >, <, >=, <= (= 1 1) T, (= (car (cons 1 (cons 2 ()))) 2) NIL (> 1 5) NIL, (< 1 2) T, (<= 5 5) T – null: per liste (T se lista e’ vuota, NIL altrimenti) Per controllare se un oggetto è un atomo o una lista: atom listp (atom 5) T, (atom nil) T, (atom (cons 1 ())) NIL, (atom (car (cons 1 ())) T (listp 2) NIL, (listp (cons 5 ())) T Predicati per test di tipo: symbolp, numberp, integerp, floatp, atom, listp 23

Funzioni predicato predefinite Predicato and (and e 1 … en) – se il risultato

Funzioni predicato predefinite Predicato and (and e 1 … en) – se il risultato della valutazione di tutte le espressioni e 1 … en è diverso da NIL, and restituisce il risultato della valutazione di en; – altrimenti restituisce NIL Predicato or (or e 1 … en) – se il risultato della valutazione di tutte le espressioni è NIL, or restituisce NIL; – altrimenti restituisce il risultato della valutazione della prima espressione diversa da NIL Quindi le espressioni possono non essere valutate tutte. 24

25

25

26

26

Altre funzioni sulle list: S-Expression* List trasforma i suoi argomenti in una lista Esempi:

Altre funzioni sulle list: S-Expression* List trasforma i suoi argomenti in una lista Esempi: (list '(12) ' a '(b 3) ' d) ((12) a (b 3) d) (list () () ) ( () () ) Append : List x List concatena i suoi argomenti in un’unica lista Esempi: (append ‘((12) a) ‘((b 3) d)) ((12) a (b 3) d) (append () '((b 3) d)) ((b 3) d) (append () () ) () 27

28

28

29

29

30

30

Programmi come dati Un “programma” in Lisp e’ costituito da liste. Un programma e’

Programmi come dati Un “programma” in Lisp e’ costituito da liste. Un programma e’ quindi manipolabile come una struttura dati base del Lisp: – Possibilità di scrivere programmi che manipolano programmi – Facilitazione dell’interprete che “vede” una rappresentazione del programma come lista. 31

Valutazione di S-espressioni L’interprete Lisp presenta un prompt ed esegue un ciclo “leggi-valuta-stampa”. •

Valutazione di S-espressioni L’interprete Lisp presenta un prompt ed esegue un ciclo “leggi-valuta-stampa”. • Leggi: parsing di una S-Exp (detta ‘forma’), scritta dall’utente • Valuta: calcola il valore associato alla S-Exp • Stampa: scrive sul video il risultato Esempio: Esempio > (+ 5 9) forma da valutare 14 32

Valutazione di S-espressioni Una S- espressione è automaticamente valutata dalla funzione eval, all’interno di

Valutazione di S-espressioni Una S- espressione è automaticamente valutata dalla funzione eval, all’interno di un ambiente che utilizza regole: Se s e’ costante numerica o uno dei simboli speciali T e NIL, eval(s) = s Se s è un simbolo, eval(s) = env(s), dove env(s) restituisce il valore associato al simbolo; se al simbolo non è associato nessun valore: eval(s) = errore. Se s è una lista (s 1 s 2 … sn): se s 1 e’ il nome di una funzione nota, eval valuta gli argomenti s 2, . . , sn da sinistra a destra e applica la funzione s 1 al valore degli argomenti. Se s 1 non e’ nota: eval(s) = errore 33 Diverso comportamento per le funzioni speciali (cond, if, etc. )

Esempi di valutazione > > > > 3 3 T T NIL (*(+ 2

Esempi di valutazione > > > > 3 3 T T NIL (*(+ 2 4)(/ 14 7)) 12 (+ 1 2 3 4) 10 (= (+ 1 2) 3) T (= (+ 1 1) 3) NIL 34

Funzioni condizionali • Implementano il costrutto di controllo • Sono necessarie per la definizione

Funzioni condizionali • Implementano il costrutto di controllo • Sono necessarie per la definizione di nuove funzioni Sintassi: Sintassi (cond (p 1 e 1) … (pn en)) – vengono valutate in sequenza le espressioni p 1 …pn , fino alla prima pi il cui valore è diverso da NIL; viene quindi restituito il risultato della valutazione della corrispondente ei – Tipicamente pn è l’espressione T (condizione di default) Esempio: (cond ((< x 0) (* x -1)) ((> x 0) (* x x)) (T 1)) 35

Funzioni condizionali Il Lisp ha altre possibilità di espressione di strutture di selezione: if,

Funzioni condizionali Il Lisp ha altre possibilità di espressione di strutture di selezione: if, case, when, . . . 1) (if e 1 e 2 e 3) Il valore restituito è quello di e 2 se e 1 è valutata T, altrimenti è e 3 (come if. . then. . else) 2) (if e 1 e 2) e’ come (if e 1 e 2 nil) if è forma speciale perché valuta solo una S-Exp fra e 2 ed e 3 (valutazione cortocircuitata) Esempi: (if (< x 0) (- x) x) (if (> x 0) (/ y x) y) (/ y x) e’ indefinito per x = 0! 36

Definizione di funzioni utente Funzione speciale DEFUN: DEFUN (defun abs (x) (if (< x

Definizione di funzioni utente Funzione speciale DEFUN: DEFUN (defun abs (x) (if (< x 0) (- x) x)) Argomenti: Argomenti nome funzione, lista parametri formali, corpo DEFUN lega il simbolo ABS alla funzione costituita dal suo terzo argomento Dal momento della valutazione di (defun abs …), la funzione utente ABS è come una funzione di sistema: > (abs -4) 4 NB: defun restituisce come valore la funzione definita. 37

Valutazione di funzioni utente Si parte con ambiente “globale” che contiene i legami predefiniti

Valutazione di funzioni utente Si parte con ambiente “globale” che contiene i legami predefiniti L’applicazione di una funzione ai suoi argomenti genera un ambiente “locale” Valutando (ABS -3), il parametro formale x viene legato (“legame fluido”) al parametro attuale -3. Finchè dura la valutazione di (ABS -3), (eval x) restituisce -3 Alla fine il legame fluido viene rilasciato. 38

Definizione di funzioni utente: esempio >(defun double (n) (* 2 n)) estende l’ambiente globale

Definizione di funzioni utente: esempio >(defun double (n) (* 2 n)) estende l’ambiente globale con il legame tra double e la sua definizione > (double 3) • estende l’ambiente globale con quello locale che contiene i legami tra parametri formali e valori dei parametri attuali • valuta il corpo della funzione • ripristina l’ambiente di partenza 39

Definizione di funzioni utente: esempi >(defun second (L) (first (rest L))) >(second '(a b

Definizione di funzioni utente: esempi >(defun second (L) (first (rest L))) >(second '(a b c)) b >(defun cons 2 (x y L) (cons x (cons y L))) >(cons 2 'a 'b '(c d e)) (a b c d e) 40

Ricorsione • Linguaggi Funzionali “puri” sono Turing-completi: ogni algoritmo esprimibile con macchina di Turing

Ricorsione • Linguaggi Funzionali “puri” sono Turing-completi: ogni algoritmo esprimibile con macchina di Turing o di Von Neumann può essere espresso • Non consentono assegnamenti, iterazioni, salti, ma usano RICORSIONE • Lisp non e’ in realtà un linguaggio funzionale puro, ma in origine lo era 41

Ricorsione: esempio Il fattoriale 0! = 1, n! = n *(n-1)! per n>0 (DEFUN

Ricorsione: esempio Il fattoriale 0! = 1, n! = n *(n-1)! per n>0 (DEFUN FATT (N) (IF (ZEROP N) 1 (* N (FATT (- N 1))))) 42

Ricorsione: valutazione del fattoriale Al prompt: > (fatt 3) n diventa legato a 3:

Ricorsione: valutazione del fattoriale Al prompt: > (fatt 3) n diventa legato a 3: (eval (fatt 3)) (eval (if (zerop 3) 1 (*3 (fatt (- 3 1))))) (* 3 (fatt 2)) (*3 (* 2 (fatt 1))) (* 3 (* 2 (* 1 (fatt 0)))) (* 3 (* 2 (* 1 1))) … 6 Eval applica la funzione al suo argomento, definendo i legami di N “in cascata” e costruendo una espressione che alla fine verra’ valutata, a partire dalla sotto-espressione piu’ annidata 43

Ricorsione con liste • la struttura ricorsiva delle liste si presta molto bene alla

Ricorsione con liste • la struttura ricorsiva delle liste si presta molto bene alla programmazione ricorsiva. • Metodo: – scrivere il valore della funzione nel caso banale (usualmente la lista vuota) – ridursi ricorsivamente al caso base operando su un argomento ridotto 44

Funzioni ricorsive • Specificare la funzione - sommatoria degli elementi di una lista (si

Funzioni ricorsive • Specificare la funzione - sommatoria degli elementi di una lista (si assume che gli - atomi siano numeri interi) Sum: List Integer • Specificare la soluzione in modo ricorsivo - se la lista è vuota il risultato è 0: Lista vuota (): 0 - altrimenti: Lista l: first(l)+sum(rest(l)) • Implementazione (defun sum (x) (if (null x) 0 (+ (first x) (sum (rest x))))) 45

Esempio di valutazione (defun sum (x) (if null(x) 0 (+ first(x) (sum (rest x)))))

Esempio di valutazione (defun sum (x) (if null(x) 0 (+ first(x) (sum (rest x))))) Esempio: sum applicata alla lista eval(sum ‘(3 4 5)) 1) (+ 3 (sum (4 5))) 9 2) (+ 4 (sum (5))) 5 4) (+ 5 (sum ())) 0 46

Esempio di ricorsione Lunghezza di una lista: numero di elementi al primo livello >(lung

Esempio di ricorsione Lunghezza di una lista: numero di elementi al primo livello >(lung '(a b c)) 3 >(lung '(((a) b) c)) 2 >(lung NIL) 0 Se lista e’ vuota, lung = 0, altrimenti 1+ lung rest: (defun lung (L) (if (null L) 0 (+ 1 (lung (rest L))))) 47

Esempio di valutazione • (lung '(a b)) • (eval (lung ‘(a b)) = (if

Esempio di valutazione • (lung '(a b)) • (eval (lung ‘(a b)) = (if (null L) 0 (+ 1 (lung (rest L)))) [L (a b)] = (+ 1 (lung (rest L))) [L (b)] = (+ 1 (if (null L) 0 (+ 1 (lung (rest L)))) = (+ 1 (lung (rest L)))) [L ()] = (+1 (+ 1 0)) = (+ 1 1) = 2 La valutazione si arresta se si raggiunge una condizione di uscita; la lista NON viene modificata 48

Un altro esempio Estrarre n-esimo elemento (al primo livello) da una lista data (che

Un altro esempio Estrarre n-esimo elemento (al primo livello) da una lista data (che si suppone abbia almeno n elementi) – (ennesimo 3 '(a b c d)) c – (ennesimo 3 '(a (b c) d)) d (defun ennesimo (n L) (if (= n 1) (first L) (ennesimo (- n 1) (rest L)))) 49

Last-l(L) Funzione che restituisce l’ultimo elemento di L (defun last-l (lst) ; ; in

Last-l(L) Funzione che restituisce l’ultimo elemento di L (defun last-l (lst) ; ; in Lisp esiste la funzione predefinita last (cond ((atom lst) ’errore ); ; eccezione ((null lst) nil); ; eccezione /nil ? ? / ((null (cdr lst)) (car lst) ); ; caso base (t (last-l (cdr lst))))); ; passo induttivo 50

Last-l(L): valutazione • ( last-l '(a b c)) • eval (last-l '(a b c)

Last-l(L): valutazione • ( last-l '(a b c)) • eval (last-l '(a b c) ) (last-l (cdr '(a b c)))) ( last-l '( b c) ) …. (last-l '(c) ) (car '(c) ) c 51

Liste come risultato • supponiamo di dover costruire la funzione my-append partire dalle funzioni

Liste come risultato • supponiamo di dover costruire la funzione my-append partire dalle funzioni CAR, CDR, CONS e i condizionali (defun my-append (l 1 l 2) (cond ((null l 1) l 2) (t (cons (car l 1) (my-append (cdr l 1) l 2))))) 52

But-last(L) Funzione che restituisce una lista meno l’ultimo elemento (defun but-last (lst) (cond ((atom

But-last(L) Funzione che restituisce una lista meno l’ultimo elemento (defun but-last (lst) (cond ((atom lst) ((null lst) nil) ((null (cdr lst)) nil) (t (cons (car lst) (but-last (cdr lst)))))) 53

But-last(L): valutazione • (but-last '(a b c)) • eval (but-last '(a b c)) (cons

But-last(L): valutazione • (but-last '(a b c)) • eval (but-last '(a b c)) (cons (first '(a b c)) (but-last (cdr '(a b c)))) ( cons 'a (but-last '(b c))) …. (cons 'a ( cons 'b '(but-last '(c)))) …. (cons 'a ( cons ’b ())) (a b) 54

Ricorsioni semplici e doppie Ricorsione semplice (“ricorsione cdr”): la ricorsione e’ sempre definita sul

Ricorsioni semplici e doppie Ricorsione semplice (“ricorsione cdr”): la ricorsione e’ sempre definita sul rest di una lista Non è sempre sufficiente. Esempio: contare gli atomi di S-exp (conta-atomi '((a b c) 1 (xyz d))) 6 55

Ricorsioni car e cdr • Base: () 0, atomo 1 (due casi, perche’ Sexp

Ricorsioni car e cdr • Base: () 0, atomo 1 (due casi, perche’ Sexp puo’ essere sia lista sia atomo) • Ip: (conta-atomi (rest L)) n. atomi di rest di L • Passo: se (first L) e’ atomo (+ 1 (conta-atomi (rest L)) altrimenti. . . ? ? 56

Ricorsioni car e cdr Ricorsione “car-cdr” (“doppia”): ricorsione anche sul car (first) di una

Ricorsioni car e cdr Ricorsione “car-cdr” (“doppia”): ricorsione anche sul car (first) di una lista (first L) e (rest L) sono sottostrutture di L: possiamo usare Ip. Ric. : (conta-atomi (first L)) e (conta-atomi rest L)) contano correttamente i loro atomi 57

Passo e composizione Passo: (+ (conta-atomi (first L)) (conta-atomi (rest L))) (defun conta-atomi (x)

Passo e composizione Passo: (+ (conta-atomi (first L)) (conta-atomi (rest L))) (defun conta-atomi (x) ; ; x puo' essere S-exp (cond ((null x) 0) ((atom x) 1) (T (+ (conta-atomi (first x)) (conta-atomi (rest x)))))) 58

Esempio ric. car-cdr: profondita’ • Profondita’ massima di annidamento di una Sexp (n. max

Esempio ric. car-cdr: profondita’ • Profondita’ massima di annidamento di una Sexp (n. max parentesi “sospese”): atomo 0, ( ) 1, (a (b ((c)) (d))) 4 • 1. Base: ovvia (caso banale atomo o lista vuota) • 2. Ip. Ric: (prof (first x)), (prof (rest x)) • 3. Passo: prof di x e’ max fra (prof (first x)) + 1 e (prof (rest x)) 59

Composizione (defun prof (x) (cond ((null x) 1) ((atom x) 0) (T (max (+

Composizione (defun prof (x) (cond ((null x) 1) ((atom x) 0) (T (max (+ 1 (prof (first x))) (prof (rest x)))))) Usiamo funz. lisp predefinita max: (defun max (m n) (if (> m n))) 60

Valutazione X = (a (b)) 1) T (max (+1 (prof 'a)) (prof '((b))) 2

Valutazione X = (a (b)) 1) T (max (+1 (prof 'a)) (prof '((b))) 2 1 2) (prof 'a) = 0 (prof '((b))) (max (+ 1 (prof '(b))) (prof ())) 2 1 3) (prof ()) = 1 (prof '(b)) (max (+ 1 (prof 'b)) (prof ())) 1 4) (prof 'b) = 0 (prof ()) = 1 1 61

Esempio: SQUASH Appiattire una S-Exp: (SQUASH '((a (b (c d)) e) f)) (a b

Esempio: SQUASH Appiattire una S-Exp: (SQUASH '((a (b (c d)) e) f)) (a b c d e f) (SQUASH 'a) (a) ? ? perche’? ? Base: lista vuota non cambia, atomo (list atom) Ip. Ric. : SQUASH (first x), SQUASH ( rest x) Passo: append di SQUASH (first x) con SQUASH ( rest x) 62

Composizione (defun squash (x) ; ; x e’ s-espressione (cond ((null x) x) ((atom

Composizione (defun squash (x) ; ; x e’ s-espressione (cond ((null x) x) ((atom x) (list x)) ; ; serve per usare append (T (append (squash (first x)) (squash (rest x)))))) NB: (atom x) e’ T anche per () (perche’ come NIL): occorre che (null x) lo preceda nel cond. . . 63

Valutazione X = (a (b)) 1) T (append (sqs (first '(a (b)))) (sqs (rest

Valutazione X = (a (b)) 1) T (append (sqs (first '(a (b)))) (sqs (rest '(a (b))))) a ((b)) append (a) (b) 2) (squash 'a) (a) (squash '((b))) (append (sqs (first '((b)))) (sqs (rest '((b))))) (b) () append (b) () 3) (squash ()) () (squash (b)) (append (sqs (first '(b))) (sqs (rest '(b)))) b 3) (squash 'b) (b) (squash ()) () () append (b) () 64

Esempio: MIRROR Immagine speculare di S-Exp: (MIRROR '(a (b (c d)) e) f)) (f

Esempio: MIRROR Immagine speculare di S-Exp: (MIRROR '(a (b (c d)) e) f)) (f (e ((d c) b) a) Base: lista vuota o atomo non cambia Ip. Ric. : L = (e 1 … en): (MIRROR 'e 1), (MIRROR '(e 2. . en)) Passo: append di (Mirror '(e 2. . en)) con (list (Mirror 'e 1)) 65

Composizione (defun mirror (x) ; x è s-exp (cond ((atom x) x) (T (append

Composizione (defun mirror (x) ; x è s-exp (cond ((atom x) x) (T (append (mirror (rest x)) (list (mirror (first x))))))) NB: Senza list, append toglierebbe una parentesi al mirror del first se questo e’ una lista; darebbe errore di parametro se fosse un atomo 66

Inversione di una lista 0: Data L = (e 1 … en), (INVERTI L)

Inversione di una lista 0: Data L = (e 1 … en), (INVERTI L) (en…e 1) 1: (INVERTI NIL) NIL 2: (INVERTI (REST L)) (en. . . e 2) 3: e 1 va posto in coda a (en … e 2): allora supponiamo che ci sia funzione CONS_END che lo faccia: (CONS_END S L) (e 1 … en S) Poi definiremo CONS_END (procediamo top-down) 67

Composizione (defun inverti (x) (cond ((null x) x) ((atom x) x) ; ; anche

Composizione (defun inverti (x) (cond ((null x) x) ((atom x) x) ; ; anche S-exp. . . (T (cons-end (first x) (inverti (rest x)))))) 68

Cons_end 1: 2: 3: 4: Base (cons_end S ()) (S) Ip. Ric. (cons_end S

Cons_end 1: 2: 3: 4: Base (cons_end S ()) (S) Ip. Ric. (cons_end S (rest L)) Passo (cons (first L) (cons_end (rest L)))) Composizione (defun cons-end (s x) (if (null x) (list s) (cons (first x) (cons-end s (rest x))))) 69

circulate(L) Scrivere la funzione circulate in modo che operi come segue al primo livello:

circulate(L) Scrivere la funzione circulate in modo che operi come segue al primo livello: > (circulate '(1 2 3 4) 'left) (2 3 4 1) > (circulate '(1 2 3 4) 'right) (4 1 2 3) (defun circulate (lst direction) (cond ((atom lst) ((null lst) nil) ((equal direction 'left) (append (cdr lst) (list (car lst)))) ((equal direction 'right) (cons (last-l lst) (but-last lst))) (T lst) )) 70

Remove (item, list) (1° livello) • Scrivere la funzione remove del LISP, che opera

Remove (item, list) (1° livello) • Scrivere la funzione remove del LISP, che opera come segue: > (remove 'a '(a b c a d)) (b c d) > (remove 'a '(a b c (a) d)) (b c (a) d) (defun my-remove (item lst) (cond ((atom lst) ((null lst) nil) ((equal (car lst) item) (my-remove item (cdr lst))) (t (cons (car lst) (my-remove item (cdr lst)))))) 71

Remove (item, list) (ogni livello) • Scrivere la funzione remove del LISP, che opera

Remove (item, list) (ogni livello) • Scrivere la funzione remove del LISP, che opera come segue: > (remove ‘a ‘(a b c a d)) (b c d) > (remove ‘a ‘(a b c (a) d)) (b c d) (defun my-remove (item lst) (cond ((atom lst) ((null lst) nil) ((equal (car lst) item) (my-remove item (cdr lst))) ((listp (car lst)) (cons (my-remove item (car lst)) (my-remove item (cdr lst)))) (t (cons (car lst) (my-remove item (cdr lst)))))) 72

(Extract-symbols L) Data una lista x costruirne una contenente i suoi elementi che sono

(Extract-symbols L) Data una lista x costruirne una contenente i suoi elementi che sono simboli 73

74

74

Da notazione prefissa a notazione infissa • Data funzione a 1 o 2 argomenti,

Da notazione prefissa a notazione infissa • Data funzione a 1 o 2 argomenti, in notazione prefissa, tradurla in forma infissa • Es: (pretoinf '(* (COS (LOG X)) (* X 1))) ((COS (LOG X)) * (X * 1)) Non consideriamo precedenza fra operatori e usiamo anche parentesi ridondanti. Espressione deve essere ben formata. 75

(defun pre 2 inf (f) (cond ((null f) f) ((atom f) f) ((equal (length

(defun pre 2 inf (f) (cond ((null f) f) ((atom f) f) ((equal (length f) 3) ; ; 2 argomenti (list (pre 2 inf (cadr f)) ; ; 1° argomento (first f) ; ; operatore (pre 2 inf (caddr f)))) ; ; 2° argomento ((equal (length f) 2) ; ; 1 argomento (list (first f) (pre 2 inf (cadr f)))) (T f))) 76

Da notazione infissa a notazione prefissa Ignoriamo precedenze operatori e ipotizziamo coppia di parentesi

Da notazione infissa a notazione prefissa Ignoriamo precedenze operatori e ipotizziamo coppia di parentesi attorno a ogni sottoespressione (se cosi’ non fosse, si complica molto perche’ occorre trattare operatore per operatore: v. Linguaggi e Traduttori). 77

(defun inf 2 pre (f) (cond ((null f) f) ((atom f) f) ((equal (length

(defun inf 2 pre (f) (cond ((null f) f) ((atom f) f) ((equal (length f) 2) (list (first f) (inf 2 pre (second f)))) ((equal (length f) 3) (list (second f) (inf 2 pre (first f)) (inf 2 pre (third f)))) (T "Errore"))) 78

Caratteristiche non funzionali del LISP Motivazione: aumentare l’efficienza di esecuzione Principale caratteristica non funzionale:

Caratteristiche non funzionali del LISP Motivazione: aumentare l’efficienza di esecuzione Principale caratteristica non funzionale: introduzione di “variabili” Ad ogni simbolo può essere associato (binding) un oggetto Lisp (valore) modificabile Assegnazione: Assegnazione espressione speciale setq: (setq <simbolo> <oggetto>) Esempio: Esempio (setq a 5) assegna all’atomo a il valore (atomo!) 5 79