370 likes | 559 Views
FUNZIONI: IL MODELLO APPLICATIVO. 1) Valutazione , nell’ environment corrente, del simbolo che denota il nome della funzione ; 2) Valutazione , nell’ environment corrente, delle espressioni che denotano i parametri ; 3) Commutazione all’ environment di definizione della funzione.
E N D
FUNZIONI: IL MODELLO APPLICATIVO 1) Valutazione, nell’environment corrente, del simbolo che denota il nome della funzione; 2) Valutazione, nell’environment corrente, delle espressioni che denotano i parametri; 3) Commutazione all’environment di definizione della funzione.
FUNZIONI: IL MODELLO APPLICATIVO 4) Chiamata della funzione; 5) Esecuzione del corpo della funzione (nel suo environment di definizione); 6) Restituzione al chiamante di • controllo • risultato con ripristino dell’environment esistente al momento della chiamata.
L’ENVIRONMENT • La definizione di una funzione introduce un nuovo bindingnell’environment di definizione della funzione • in C, il global environment • Al momento dell’invocazione, si crea un nuovo environment • una struttura che contiene i binding dei parametri e degli identificatori dichiarati localmente alla funzione.
ESEMPIO int max (int x, int y ){ return x>y ? x : y; } • L’environment corrente viene arricchito di un nuovo binding:max / CodiceDellaFunzione • Quando max viene chiamata, si commuta a un nuovo environment, in cui sono definite le variabili intere x e y
COMUNICAZIONE CLIENTE SERVITORE Il cliente passa informazioni al servitore mediante una serie di parametri attuali. • Parametri formali: • sono specificati nella dichiarazione del servitore • esplicitano il contratto fra servitore e cliente • indicano cosa il servitore si aspetta dal cliente • Parametri attuali: • sono trasmessi dal cliente all’atto della chiamata • devono corrispondere ai parametri formaliin numero, posizione e tipo
COMUNICAZIONE CLIENTE SERVITORE Il cliente passa informazioni al servitore mediante una serie di parametri attuali. I Parametri attuali sono legati ai parametri formalial momento della chiamata,in modo dinamico. Tale legame: • vale solo per l’invocazione corrente • vale solo per la durata della funzione.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); }
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 1) Valutazione del simbolo znell’environment corrente Si trova che z vale 8.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 2) Calcolo dell’espressione 2*znell’environment corrente Si trova che vale 16.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 3) Invocazione della funzione max con parametri attuali16 e 13. Il controllo passa al servitore.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 4) I parametri formali x e y vengono legati ai parametriattuali 16 e 13. Inizia l’esecuzione del servitore.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 5) Viene valutata l’espressionecondizionale nell’environment del servitore. Il risultato è 16.
IL NOSTRO ESEMPIO • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); } 6) Il valore così determinato (16)viene restituito al cliente. Il servitore termina e il controllo torna al cliente.
IL NOSTRO ESEMPIO 7) Il valore restituito (16) viene usato per inizializzare lavariabile m (nell’environment del cliente) • Il servitore... intmax (int x, int y ){ return x>y ? x : y; } • … e un possibile cliente: main(){ int z = 8; int m = max(2*z,13); }
RIASSUNTO All’atto dell’invocazione di una funzione: • si crea una nuova attivazione (istanza) del servitore • si alloca la memoriaper i parametri(e le eventuali variabili locali) • si trasferiscono i parametri al servitore • si trasferisce il controllo al servitore • si esegue il codice della funzione.
PASSAGGIO DEI PARAMETRI In generale, un parametro può essere trasferito: • per valore o copia (by value) • si trasferisce il valore del parametro attuale • per riferimento (by reference) • si trasferisce un riferimentoal parametro attuale
PASSAGGIO PER VALORE • si trasferisce una copia del valore del parametro attuale z 45 cliente
PASSAGGIO PER VALORE • si trasferisce una copia del valore del parametro attuale valore (copiato) di z copia z 45 w 45 istanza del servitore cliente servitore
PASSAGGIO PER VALORE Ogni azione fatta su w è strettamente locale al servitore • si trasferisce una copia del valore del parametro attuale valore (copiato) di z copia z 45 w 45 istanza del servitore cliente servitore
PASSAGGIO PER RIFERIMENTO • si trasferisce un riferimento al parametro attuale z 45 cliente
PASSAGGIO PER RIFERIMENTO • si trasferisce un riferimento al parametro attuale riferimento a z (indirizzo) riferimento z 45 w istanza del servitore cliente servitore
PASSAGGIO PER RIFERIMENTO Ogni azione fatta su w è in realtà fatta sulla variabile z del cliente! • si trasferisce un riferimento al parametro attuale riferimento a z (indirizzo) riferimento z 45 w istanza del servitore cliente servitore
PASSAGGIO DEI PARAMETRI IN C In C, i parametri sono trasferiti sempre e solo per valore (by value) • si trasferisce una copia del parametro attuale, non l’originale! • tale copia è strettamente privata e locale a quel servitore • il servitore potrebbe quindi alterare il valore ricevuto, senza che ciò abbia alcun impatto sul cliente
PASSAGGIO DEI PARAMETRI IN C In C, i parametri sono trasferiti sempre e solo per valore (by value) Conseguenza: • è impossibile usare un parametro per trasferire informazioni verso il cliente • per trasferire (una) informazione al cliente si sfrutta il valore di ritorno della funzione
ESEMPIO: VALORE ASSOLUTO • Definizione formale: |x|: N N |x| vale x se x 0 |x| vale -x se x 0 • Codifica sotto forma di funzione C: int valAss(int x) { return (x<0) ? -x : x; }
ESEMPIO: VALORE ASSOLUTO • Servitore & Cliente: int valAss(int x) { return (x<0) ? -x : x; } main(){ int z = -87; int absz = valAss(z); int abs4 = valAss(4); }
ESEMPIO: VALORE ASSOLUTO Quando valAss(z) viene chiamata, il valore attuale di z, valutato nel- l’environment corrente (-87), viene copiato e passato a valAss. • Servitore & Cliente: int valAss(int x) { return (x<0) ? -x : x; } main(){ int z = -87; int absz = valAss(z); int abs4 = valAss(4); }
ESEMPIO: VALORE ASSOLUTO • Servitore & Cliente: int valAss(int x) { return (x<0) ? -x : x; } main(){ int z = -87; int absz = valAss(z); int abs4 = valAss(4); } valAss riceve quindi una copia del valore -87 e la lega al simbolo x. Poi si valuta l’espressione, che qui vale 87, e si restituisce questo valore.
ESEMPIO: VALORE ASSOLUTO • Servitore & Cliente: int valAss(int x) { return (x<0) ? -x : x; } main(){ int z = -87; int absz = valAss(z); int abs4 = valAss(4); } Il valore restituito (87) viene usato per inizializzare la variabile absz.
ESEMPIO: MASSIMO DI DUE NUMERI • Definizione formale: max: N N N max(x,y) vale x se x y max(x,y) vale y se x < y • Codifica sotto forma di funzione C: int max(int x, int y) { return (x<y) ? y : x; }
ESEMPIO: MASSIMO DI DUE NUMERI • Servitore & Cliente: int max(int x, int y) { return (x<y) ? y : x; } main(){ int z = -87, y = 12; int m = max(z,18); int n = max(4*y,z+100); }
ESEMPIO: MASSIMO DI DUE NUMERI Si valutano le due espressioni che costituiscono i parametri attuali (nel- l’environment del main) e si trasmette alla funzione copia dei valori ottenuti. • Servitore & Cliente: int max(int x, int y) { return (x<y) ? y : x; } main(){ int z = -87, y = 12; int m = max(z,18); int n = max(4*y,z+100); }
ESEMPIO: MASSIMO DI DUE NUMERI • Servitore & Cliente: int max(int x, int y) { return (x<y) ? y : x; } main(){ int z = -87, y = 12; int m = max(z,18); int n = max(4*y,z+100); } La funzione riceve copia dei valori -87 e 18, e li lega ai simboli x e y. Poi si valuta l’espressione. Il risultato (18) è restituito al main chiamante.
PASSAGGIO DEI PARAMETRI IN C Perché il C adotta sempre e solo il passaggio per valore (by value)? • è sicuro: le variabili del chiamante e del chiamato sono completamente disac-coppiate • consente di ragionare per componenti e servizi: la struttura interna dei singoli componenti è irrilevante
PASSAGGIO DEI PARAMETRI IN C Limiti: • consente di restituire al cliente solo valori di tipo (relativamente) semplice • non consente di restituire collezioni di valori • non consente di scrivere componenti software il cui scopo sia diverso dal calcolo di una espressione
PASSAGGIO DEI PARAMETRI Molti linguaggi mettono a disposizione il passaggio per riferimento (by reference) • non si trasferisce una copia del valore del parametro attuale • si trasferisce un riferimento al parametro, in modo da dare al servitore accesso di- retto al parametro in possesso del cliente • il servitore accede e modifica direttamente il dato del cliente.
PASSAGGIO DEI PARAMETRI IN C Il C non supporta direttamente il passaggio per riferimento • è una grave mancanza! • il C lo fornisce indirettamente solo per alcuni tipi di dati • ergo, occorre costruirselo quando serve.(vedremo dei casi) Il C++ e Java invece lo forniscono.