Brevissima introduzione al Lisp



Похожие документы
Brevissima introduzione al Lisp

4 3 4 = 4 x x x 10 0 aaa

Funzioni in C. Violetta Lonati

Programmazione Funzionale

Le variabili. Olga Scotti

Alcune nozioni di base di Logica Matematica

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

Matematica in laboratorio

Alessandro Pellegrini

LE FUNZIONI A DUE VARIABILI

Laboratorio di Informatica

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

Dispense di Informatica per l ITG Valadier

ALGEBRA DELLE PROPOSIZIONI

Corso di Informatica

I sistemi di numerazione

Funzioni funzione dominio codominio legge argomento variabile indipendente variabile dipendente

Iniziamo con un esercizio sul massimo comun divisore: Esercizio 1. Sia d = G.C.D.(a, b), allora:

Lezione 8. La macchina universale

Proof. Dimostrazione per assurdo. Consideriamo l insieme complementare di P nell insieme

Algebra Booleana ed Espressioni Booleane

Esempi di algoritmi. Lezione III

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Algoritmi e strutture dati. Codici di Huffman

LA NOTAZIONE SCIENTIFICA

Esercitazione Informatica I AA Nicola Paoletti

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Algebra booleana. Si dice enunciato una proposizione che può essere soltanto vera o falsa.

( x) ( x) 0. Equazioni irrazionali

Dimensione di uno Spazio vettoriale

risulta (x) = 1 se x < 0.

Appunti di informatica. Lezione 2 anno accademico Mario Verdicchio

Convertitori numerici in Excel

3 GRAFICI DI FUNZIONI

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

1 Serie di Taylor di una funzione

FORMULE: Operatori matematici

Sistemi di Numerazione

Complemento al corso di Fondamenti di Informatica I corsi di laurea in ingegneria, settore dell informazione Università la Sapienza Consorzio Nettuno

Algebra Booleana 1 ALGEBRA BOOLEANA: VARIABILI E FUNZIONI LOGICHE

EXCEL FUNZIONI PRINCIPALI

Algebra di Boole ed Elementi di Logica

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Capitolo 5. Funzioni. Grafici.

Test Excel conoscenze di Base

Testi di Esercizi e Quesiti 1

Parte II Indice. Operazioni aritmetiche tra valori rappresentati in binario puro. Rappresentazione di numeri con segno

Obiettivo Principale: Aiutare gli studenti a capire cos è la programmazione

Esponenziali elogaritmi

+ / operatori di confronto (espressioni logiche/predicati) / = > < Pseudo codice. Pseudo codice

4. Operazioni elementari per righe e colonne

Semantica operazionale dei linguaggi di Programmazione

2. Leggi finanziarie di capitalizzazione

Lezioni di Matematica 1 - I modulo

LA TRASMISSIONE DELLE INFORMAZIONI QUARTA PARTE 1

Alcune regole di base per scrivere un programma in linguaggio C

Corrispondenze e funzioni

SCHEDA DI RECUPERO SUI NUMERI RELATIVI

Algebra Di Boole. Definiamo ora che esiste un segnale avente valore opposto di quello assunto dalla variabile X.

Risolvere un problema significa individuare un procedimento che permetta di arrivare al risultato partendo dai dati

1. PRIME PROPRIETÀ 2

Numeri naturali numeri naturali minore maggiore Operazioni con numeri naturali

Concetto di Funzione e Procedura METODI in Java

La distribuzione Normale. La distribuzione Normale

Funzioni. Funzioni /2

Introduzione all Information Retrieval

La selezione binaria

LABORATORIO DI MATEMATICA RENDITE, AMMORTAMENTI, LEASING CON EXCEL

LABORATORIO DI PROGRAMMAZIONE EDIZIONE 1, TURNO B

Esempi di funzione. Scheda Tre

Documentazione esterna al software matematico sviluppato con MatLab

Introduzione al MATLAB c Parte 2

Il principio di induzione e i numeri naturali.

E possibile modificare la lingua dei testi dell interfaccia utente, se in inglese o in italiano, dal menu [Tools

ESEMPIO 1: eseguire il complemento a 10 di 765

Librerie digitali. Video. Gestione di video. Caratteristiche dei video. Video. Metadati associati ai video. Metadati associati ai video

Un metodo per il rilevamento degli errori: la tecnica del Bit di Parità

Appunti sulla Macchina di Turing. Macchina di Turing

Matematica generale CTF

ALGEBRA RELAZIONALE RIEPILOGO

APPUNTI DI MATEMATICA ALGEBRA \ INSIEMISTICA \ TEORIA DEGLI INSIEMI (1)

3 - Variabili. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a prof.

Luigi Piroddi

11) convenzioni sulla rappresentazione grafica delle soluzioni

Elementi di Psicometria con Laboratorio di SPSS 1

4. Operazioni aritmetiche con i numeri binari

Probabilità discreta

Variabili e tipi di dato

Schemi delle Lezioni di Matematica Generale. Pierpaolo Montana

13. Campi vettoriali

Uso di base delle funzioni in Microsoft Excel

Correttezza. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 10. A. Miola Novembre 2007

Statistica e biometria. D. Bertacchi. Variabili aleatorie. V.a. discrete e continue. La densità di una v.a. discreta. Esempi.

Prodotto libero di gruppi

Ottimizazione vincolata

Транскрипт:

Brevissima introduzione al Lisp Versione preliminare Giorgio Ausiello, Luigi Laura May 16, 2001 Queste pagine costituiscono un riferimento per gli studenti del corso di Informatica Teorica e non hanno nessuna pretesa di completezza riguardo al linguaggio Lisp. Per gli scopi del corso é di interesse mostrare come si possano definire funzioni con il linguaggio Lisp. Da notare che queste pagine sono state scritte con l idea di fornire allo studente del materiale da usare davanti a un interprete lisp, ed é per questo che cominciamo presentando l interprete lisp come una calcolatrice interattiva, per consentire al lettore di familiarizzare prima con la forma prefissa, poi incrementalmente passare ad argomenti sempre piú complessi, fino a presentare un interprete lisp scritto in lisp. 1 L interprete lisp come una calcolatrice Forma prefissa prefissa: Nel lisp le espressioni sono rappresentate mediante la forma (+ 8 3) corrisponde a 8+3 e l interprete lisp restituisce correttamente 11. Nella forma prefissa il primo elemento di una parentesi é l operatore, e i successivi (da destra verso sinistra) sono gli operandi. Nel seguito scriveremo le espressioni lisp in una riga e quello che viene restituito dall interprete nella successiva, ad esempio: (* 4 2) 8 (- (* 4 2) (+ 3 2)) 3 Tipi numerici di dato: float, integer e ratio Il lisp ci fornisce tre tipi numerici di dato. Consideriamo la seguente divisione tra numeri interi (integer): 1

(/ 8 4) 2 Nell esempio precedente il risultato e un numero intero (che ci viene restituito dall interprete lisp). Se, viceversa, il risultato non é un numero intero il lisp restituisce un ratio, ovvero un rapporto: (/ 5 2) 5/2 Con l istruzione FLOAT possiamo forzare il lisp a restituirci il valore reale (float) di un rapporto: (FLOAT (/ 5 2)) 2.5 Per ottenere un risultato equivalente possiamo scrivere i numeri direttamente nel formato float, come nel seguente esempio: (/ 5.0 2.0) 2.5 Operazioni matematiche operazioni matematiche: Tra le primitive fornite dal lisp segnalamo le seguenti (MAX 7 6 8) 8 (MIN 7 6 8) 6 (ABS -8) 8 (EXPT 2 3) 8 (SQRT 25) 5 Massimo Minimo Valore assoluto Elevamento a potenza Radice quadrata (ROUND 1.25) 1 (ROUND 1.75) 2 (TRUNCATE 14 4) 3 Arrotondamento Divisione tra interi (REM 14 4) REMainder: resto della 2 divisione tra interi Notiamo che ROUND restituisce il numero intero il cui valore piú si avvicina a quello dell argomento (di tipo float). Se X é intero vale la seguente: 2

X=(ROUND (FLOAT X)) Se X,Y sono interi e Y diverso da 0 vale la relazione: (+ (* (TRUNCATE X Y) Y) (REM X Y)=X Il numero di operandi varia (naturalmente) da funzione a funzione: N: +,*,-, MAX, MIN 2: TRUNCATE, REM, EXPT 1: ABS, SQRT, FLOAT 2 Definizione di funzioni numeriche In lisp si distingue tra programmi, procedure e primitive. Un programma é un insieme di procedure, mentre le primitive sono le procedure fornite dal linguaggio lisp. Per definire una procedura si usa il comando DEFUN che ha la seguente sintassi: (DEFUN <nome procedura> (<lista parametri>) <corpo procedura>) Per esempio posso definire la seguente procedura MODULO che prende in ingresso le due componenti x e y di un vettore bidimensionale e ne restisce il modulo (= x 2 + y 2 ): (DEFUN MODULO (X Y) (SQRT (+ (* X X) (* Y Y)))) MODULO la procedura appena definita puó essere chiamata come al solito con la notazione prefissa, ovvero: (MODULO 3 4) 5.0 Nel definire funzioni si puó usare la ricorsione, come nel seguente (classico) esempio del calcolo del fattoriale di un numero: 3

(DEFUN FATTORIALE (N) (COND ((= N 1) 1) (T (FATTORIALE (- N 1))))) Nella prossima sezione definiremo formalmente la sintassi della primitiva COND che abbiamo usato nella definizione della funzione fattoriale. Esercizi 1. Scrivere in forma prefissa la seguente espressione: ((3 + 2) 5 + (4 2)) ((2 + 3)/5) 2. Scrivere una funzione lisp che prende due numeri (positivi) e restituisce la radice quadrata del minore dei due. 3. Scrivere una funzione lisp ALCUBO che prende un numero e lo eleva al cubo. 3 Atomi, liste e funzioni su liste Prima di introdurre le liste, tipo di dato fondamentale nel linguaggio lisp (l acronimo lisp sta per list processor!) vediamo due primitive fondamentali: SETQ e QUOTE che consentono, rispettivamente, di assegnare valori a variabili e di impedire la valutazione di una espressione. L istruzione SETQ L istruzione SETQ prende in ingresso 2 operandi ed assegna al primo il valore del secondo: (SETQ PIGRECO 3.14) 3.14 A questo punto PIGRECO vale 3.14. La seguente istruzione: (SETQ A PIGRECO) 3.14 assegna correttamente ad A il valore di PIGRECO, e quindi 3.14. Se vogliamo fare piú assegnazioni insieme, possiamo scrivere semplicemente: (SETQ PIGRECO 3.14 RADICEDIDUE 1.41 A PIGRECO) 3.14 Infatti SETQ accetta n coppie di operandi ed assegna a ogni primo elemento di una coppia il valore del secondo elemento corrispondente. Notiamo che se l interprete lisp esegue una serie di operazioni (in questo caso assegnazioni) restituisce sempre l ultimo valore. 4

L operatore QUOTE Abbiamo visto che nella notazione prefissa il primo elemento di una lista é l operatore, e gli altri sono gli operandi. Ma se voglio avere una lista come operando? Come faccio a far capire all interprete lisp che la lista che si trova davanti é l operando e non un qualcosa da valutare? In altre parole, come distinguo (+ 4 2) dalla lista composta dai 3 elementi +,4 e 2? Questa funzione viene assolta dall operatore QUOTE (apice): (SETQ CLASSIFICA (QUOTE (ROMA LAZIO JUVE))) (ROMA LAZIO JUVE) Solitamente l operatore QUOTE viene abbreviato con l apice ( ) davanti alla parentesi, quindi la seguente istruzione é equivalente alla precedente: (SETQ CLASSIFICA (ROMA LAZIO JUVE)) (ROMA LAZIO JUVE) Notiamo la differenza tra le seguenti istruzioni: (SETQ A B) B (SETQ C A) B (SETQ C A) A Assegna ad A il valore B Assegna a C il valore di A, quindi B Assegna a C il valore A L operatore CAR restituisce il primo ele- Operazioni su liste: CAR e CDR mento di una lista: (CAR (A B C)) A Una lista puó contenere delle liste al suo interno. Per esempio: (CAR ((A B)(C D)) (A B) L operatore CDR restituisce la lista privata del primo elemento: (CDR (A B C)) (B C) (CDR ((A B)(C D)) ((C D)) Bisogna prestare particolare attenzione al fatto che CDR restituisce sempre 5

una lista, mentre CAR restituisce un elemento (che puó anche essere una lista). CAR e CDR possono essere combinati tra di loro (fino a un massimo di 4 volte) CDDR é il CDR del CDR. Altri esempi: (CADR (1 2 3 4)) ;Equivale a (CAR (CDR (1 2 3 4))) 2 (CDAR ((1 2) (2 3) (3 4))) ;Equivale a (CDR (CAR ((1 2) (2 3) (3 4)))) (2) Costruttori di liste In lisp ci sono tre primitivi che consentono di costruire delle liste: LIST,APPEND e CONS. LIST prende n operandi e restituisce la lista i cui elementi sono gli n operandi: (LIST A) (A) (LIST A A) (A A) (LIST A (CDR (A B C))) (A (B C)) APPEND prende n liste e restituisce la lista composta dagli elementi delle n liste: (APPEND (1 2) (3 4)) (1 2 3 4) (APPEND (1 2) (CDR (1 2))) (1 2 CDR (1 2)) CONS prende due operandi: un elemento e una lista e restituisce la lista con lelemento inserito al primo posto: (CONS A (B C)) (A B C) (CONS A (CDR (B C))) (A C) Altre operazioni su liste: REVERSE, LENGTH, SUBST e LAST REVERSE prende come argomento una lista e restituisce la lista in cui gli elementi di livello piú elevato si sono scambiati di posto: 6

(REVERSE (1 2)) (2 1) (REVERSE (1 2 (3 4))) ((3 4) 2 1) LENGTH conta il numero di elementi di livello piú elevato presenti in una lista: (LENGTH (A B)) 2 (LENGTH (A B (C D))) 3 Notiamo che sia REVERSE che LENGTH agiscono sugli elementi di livello piú elevato in una lista, e che considerano atomi e liste allo stesso modo. Quindi LENGTH su una lista composta da 3 atomi restituirá 3, e lo stesso fará su una lista composta di 3 liste. SUBST ha il seguente formato: (SUBST <new expression> <old atom> <expression to substitute>) alcuni esempi: (SUBST A B (A B C)) (A A C) (SUBST B A (A B C)) (B B C) (SUBST A B (B ((B) B) A C)) (A ((A) A) A C) LAST restituisce una lista che contiene l ultimo elemento della lista datagli come argomento (notare la differenza con CAR, che restituisce un elemento): (LAST (A B C)) (C) (LAST ((A) (B) (C))) ((C)) (LAST A) ERRORE! 7

Definizione di procedure su liste Come abbiamo visto per funzioni numeriche, con la stessa sintassi (DEFUN) é possibile definire nuove procedure che operano su liste. Per esempio definiamo la funzione RUOTASX che prende una lista in ingresso e la ruota a sinistra, ovvero prende il primo elemento e lo inserisce in fondo alla lista. (DEFUN RUOTASX (L) (APPEND (CDR L) (LIST (CAR L)))) RUOTASX Le funzioni appena definite possono essere usate nella definizione di nuove funzioni, se vogliamo scrivere la funzione che ruota a destra una lista, (RUOTADX) possiamo sfruttare la funzione RUOTASX appena definita. L idea é la seguente: ruotare una lista a destra é equivalente a invertire una lista, ruotarla a sinistra e invertirla di nuovo. Notiamo che se avessimo voluto usare la funzione LAST per prendere l ultimo elemento e inserirlo in cima avremmo poi avuto il problema di eliminarlo dalla lista originale, cosa che in RUOTASX veniva svolta da CDR. (DEFUN RUOTADX (L) (REVERSE (RUOTASX (REVERSE L)))) RUOTADX Le procedure lisp che abbiamo visto finora restituivano in uscita un solo valore (o dato). Questa é una caratteristica del lisp, e per avere piú di un valore in uscita da una procedura si puó far restituire una lista contenente i valori. Predicati Nel linguaggio lisp esistono due costanti a cui sono associati i valori booleani vero e falso. Il valore falso é rappresentato da NIL, mentre il valore vero da T, anche se per definizione é vera qualsiasi cosa diversa da NIL. Esistono numerose procedure, chiamate predicati, che restituiscono valori di verit. Tra queste: ATOM verifica che il suo argomento sia un atomo: (ATOM (A B C)) NIL (ATOM A) NIL Allo stesso modo LISTP restituisce T se il suo argomento é una lista: (LISTP (A B C)) T 8

(LISTP A) NIL A parte ATOM parecchi predicati finiscono per P, mnemonico per predicato. Tra questi i seguenti predicati restituiscono T se l argomento é: NUMBERP un numero ZEROP 0 ODDP (un numero) pari EVENP (un numero) dispari MINUSP (un numero) minore di 0 MEMBER prende in ingresso un elemento e una lista e restituisce T se la lita contiene l elemento: MEMBER A (B B A C) (A C) MEMBER A (B B C) NIL Il predicato EQUAL verifica che i suoi (2) argomenti siano uguali. quindi: Abbiamo (SETQ A B) ; Assegno ad A il valore B B (EQUAL A A) T (EQUAL A B) T (EQUAL A B) NIL Prendere decisioni nelle funzioni: la primitiva COND Adesso che abbiamo visto i predicati vediamo come usarli all interno delle funzioni che scriviamo. Nella definizione della funzione fattoriale avevamo visto utilizzata la primitiva COND. La sintassi é la seguente: (COND (test1 azione1) 9

(test2 azione2)... (testn azionen)) Il comportamento di COND é il seguente: viene valutato il test1, se vale T viene eseguita l azione1, altrimenti si passa al test2 e cosí via finche non si trova (se si trova) un test che restituisce T. In tal caso si esegue l azione corrispondente e poi si esce. Per esempio la funzione FIBONACCI puó essere definita nel modo seguente: (DEFUN FIBONACCI (N) (COND ((= N 0) 1) ((= N 1) 1) (T (+ (FIBONACCI (- N 1))(FIBONACCI (- N 2)))))) 4 Funzioni come parametri di funzioni Supponiamo di voler scrivere una funzione che si comporti nel seguente modo: prenda in ingresso una funzione F e un altro argomento X, e applichi due volte la F su X (ovvero F(F(X))). Definisco la funzione nel seguente modo: (DEFUN DUEVOLTE (F X) (F (F X))) ; Sbagliata! DUEVOLTE A questo punto l istruzione (DUEVOLTE SQRT 81) ERRORE restituisce errore perché la variabile SQRT non ha valore (per vederla come funzione dovrei farla precedere da una parentesi). Allo stesso modo (DUEVOLTE SQRT 81) ERRORE restituisce errore perché SQRT viene visto come una costante (quale é!). Per poter chiamare funzioni (incognite nel momento in cui definiamo una funzione) ci serve l operatore FUNCALL, che ha la sintassi: FUNCALL <nomefunzione> <operandi della funzione> Quindi la corretta definizione della funzione DUEVOLTE é: 10

(DEFUN DUEVOLTE (F X) (FUNCALL F (FUNCALL F X))) DUEVOLTE da cui (DUEVOLTE SQRT 81) 3.0 La funzione SQRT in questo caso operava su un solo elemento. Supponiamo di voler effettuare una somma (o sottrazione) di N elementi, contenuti in una lista. Come facciamo a passarli come parametri a FUNCALL? Supponiamo che gli N elementi siano nella lista L, bisognerebbe scrivere qualcosa del tipo: (FUNCALL + (CAR (CDR L)) (CAR (CDR (CDR L))).. (CAR (CDR (..CDR L))) In questo caso si usa la primitiva APPLY, che prende in ingresso una funzione e una lista e chiama la funzione sugli elementi della lista (se volevo chiamare la funzione sulla lista usavo FUNCALL!): (APPLY + L) é equivalente a (se L1..Ln sono gli elementi di L: (+ L1 L2.. Ln). 11