Corso di Laurea in Informatica (AA 2005/2006) Linguaggi di Programmazione - elementi Gabriella Pasi e Carla Simone [email protected] [email protected] Programma del corso Introduzione ai paradigmi di programmazione PARTE A: Introduzione alle grammatiche (base formale dei linguaggi) PARTE B: Linguaggi funzionali – Il concetto di ricorsione – Introduzione al linguaggio Lisp PARTE C: La programmazione concorrente – Modellazione di sistemi concorrenti – La notazione algebrica FSP e la notazione grafica delle Reti di Petri PARTE D: Linguaggi logici – Introduzione al linguaggio Prolog – Introduzione alla Logica Matematica (base formale dei linguaggi logici) Modalità di esame L’esame è costituito da tre parti: • prova scritta • realizzazione di progetti • discussione orale dello scritto e dei progetti La prova scritta potrà essere effettuata mediante DUE compitini, che potranno essere sostenuti durante il corso: • primo compitino: mese di Novembre • secondo compitino: mese di Gennaio Nel caso in cui uno dei due compitini risultasse insufficiente è consentito un recupero degli argomenti ad esso relativo SINO ALL’APPELLO DI APRILE compreso. Dopo tale appello sarà necessario rifare interamente la prova scritta. Modalità di esame Il testo dei progetti sarà pubblicato sul sito web del corso (http://old.disco.unimib.it/simone/ling_prog_el/). La consegna dei progetti dovrà avvenire mediante invio di file al seguente indirizzo (quello relativo al proprio docente!) ENTRO UNA SETTIMANA PRIMA dello scritto dell’appello prescelto. [email protected] [email protected] per gli studenti con cognome che inizia con lettera A-L per gli studenti con cognome che inizia con lettera M-Z La prima prova scritta e’ il giorno 27 Gennaio. Se si vuole sostenere l’orale in questo appello i progetti devono quindi essere consegnati ENTRO IL GIORNO 20. Linguaggi di programmazione: una possibile classificazione – LINGUAGGI IMPERATIVI – LINGUAGGI FUNZIONALI – LINGUAGGI LOGICI – LINGUAGGI A OGGETTI Questa classificazione corrisponde paradigmi di programmazione. a distinti I linguaggi di programmazione possono essere SEQUENZIALI o CONCORRENTI. Paradigma imperativo (procedurale) Le caratteristiche essenziali e la struttura dei linguaggi imperativi sono strettamente legate all’architettura di Von Neumann. L’architettura di Von Neumann è costituita da due componenti fondamentali: – memoria (componente passiva) – processore (componente attiva) La principale attività del processore e’ eseguire calcoli e assegnare valori a celle di memoria concetto di variabile come astrazione di cella di memoria. I linguaggi ASSEMBLER, FORTRAN, Pascal, C (ad esempio) sono basati su distinti livelli di astrazione di questa architettura. La macchina di Von Neuman I/O Memory CPU fetch instr. execute store result Paradigma imperativo (procedurale) I linguaggi imperativi adottano uno stile prescrittivo. – un programma scritto in un linguaggio imperativo prescrive le operazioni che il processore deve compiere (ad es. assegnamento). – Esecuzione delle istruzioni nell’ordine in cui appaiono nel programma (eccezione: strutture di controllo) Realizzati sia attraverso interpretazione (BASIC,...) sia mediante compilazione (C, Pascal, FORTRAN, ...) Nati per più per manipolazione numerica che simbolica Paradigma imperativo (procedurale) Programma = Algoritmo + dati La struttura del programma consiste in: • una parte di dichiarazione in cui si dichiarano tutte le variabili del programma e il loro tipo: • una parte che descrive l’algoritmo risolutivo utilizzato, mediante istruzioni del linguaggio. Le istruzioni si dividono in: • istruzioni di lettura e scrittura • istruzioni di assegnamento (astrazione di cella di memoria) • istruzioni di controllo Definizione di paradigmi di programmazione alternativi Motivazioni – Necessità di gestire applicazioni a più alto livello di astrazione – Tentativo di sviluppare programmi più concisi, più semplici da scrivere, più vicini alla logica del problema, la cui correttezza sia più “semplice” da verificare – PROGRAMMAZIONE FUNZIONALE – PROGRAMMAZIONE LOGICA – PROGRAMMAZIONE A OGGETTI Paradigmi funzionale e logico: caratteristiche comuni Linguaggi ad ”altissimo livello”: utilizzabili anche da nonprogrammatori. Generati per manipolazione simbolica non numerica. Concetti di programma e di struttura dati non nettamente separati (un programma è specificato per mezzo di una struttura dati). Basati su concetti matematici e non come astrazioni della macchina di Von Neumann. Non richiedono dichiarazioni di variabili. I linguaggi funzionale e logico adottano uno stile dichiarativo. Paradigma funzionale Concetto primitivo: funzione – Una funzione è una regola di associazione tra due insiemi, che associa a ogni elemento del primo insieme (dominio) un elemento del secondo insieme (codominio). – La definizione di una funzione ne specifica il dominio, il codominio e la regola di associazione. Ad esempio: incr: N N incr(x) = x + 1. – Dopo averne dato definizione, una funzione può essere applicata a un elemento del dominio (argomento) per restituire l’elemento del codominio ad esso associato (valutazione): incr(3) = 4. Paradigma funzionale L’unica operazione utilizzata nel funzionale è l’applicazione di funzioni. paradigma Il ruolo dell’interprete di un linguaggio funzionale è valutare il programma e produrre un valore: nel paradigma funzionale “puro” il valore di una funzione è determinato soltanto dal valore dei suoi argomenti, e non da variabili (assenza di effetti collaterali). Il concetto di variabile utilizzato è quello di variabile matematica valori non mutabili (nessun assegnamento). L’essenza della programmazione funzionale è combinare funzioni (utilizzo del concetto di RICORSIONE). Paradigma funzionale Programma = Funzione La struttura del programma consiste nella definizione di una funzione. L’esecuzione del programma consiste nella valutazione di tale funzione. La struttura dati fondamentale è la lista Un programma è definito come una lista (programma coincide con struttura dati) Linguaggio LISP (LISt Processing) Proposto nel 1958 da John McCarthy. Originariamente era funzionale puro. Esistono molti ambienti di programmazione Lisp: • InterLisp • MacLisp • CommonLisp Linguaggio LISP (LISt Processing) Esempio di programma Lisp (defun member (item list) (cond ((null list) nil) ((equal item (car list)) T) (T (member item (cdr list))))) (member ’A ’(B C D)) • Il programma è una struttura dati • Non c’è dichiarazione di tipo • Non c’è assegnamento Paradigma logico Concetto primitivo: deduzione logica Base: logica formale Obiettivo: formalizzare il ragionamento Programmare significa: – descrivere il problema con formule del linguaggio – interrogare il sistema, che effettua deduzioni sulla base della conoscenza rappresentata Paradigma logico Programma = Conoscenza + controllo Stile dichiarativo: la conoscenza del problema è espressa indipendentemente dal suo utilizzo (COSA non COME); Alta modularità e flessibilità Definire un linguaggio logico significa definire come il programmatore può esprimere la conoscenza e quale tipo di controllo può utilizzare: – Problematiche conoscenza di RAPPRESENTAZIONE della Linguaggio Prolog Un programma Prolog è costituito da: – Asserzioni incondizionate (fatti): – Asserzioni condizionate (o regole): A A IF B,C,D,… •A: è la conclusione (conseguente) •B,C,D: sono le premesse (o antecedenti) Una interrogazione ha la forma: ? A, B, C, … Linguaggio Prolog ESEMPIO: due individui sono colleghi se lavorano per la stessa ditta REGOLA collega(X,Y):- lavora(X,Z), lavora(Y,Z), diverso(X,Y). FATTI lavora(emp1,ibm). lavora(emp2,ibm). lavora(emp3,txt). lavora(emp4,olivetti). lavora(emp5,txt). :- collega(X,Y). Confronto tra programmazione prescrittiva e programmazione dichiarativa Problema: ordinare una lista STILE PRESCRITTIVO: Controlla prima se la lista è vuota; se sì dai come risultato la lista vuota. Altrimenti calcola una permutazione L’ di L e controlla se è ordinata; se sì termina dando come risultato L’, altrimenti calcola un’altra permutazione di L etc.… STILE DICHIARATIVO: Il risultato dell’ordinamento di una lista vuota è la lista vuota. Il risultato dell’ordinamento di una lista L è L’ se la lista L’ è ordinata ed è la permutazione di L.