lunedì, giugno 25, 2007

Side effects in Matlab

Come tutti i "matlabbisti" sanno, in Matlab l'assegnamento ed il passaggio dei parametri è virtualmente per copia, ovvero virtualmente ogni volta che si assegna una variabile ad un'altra o che si passa una variabile a una funzione questa viene copiata per intero in maniera tale da non avere side effects. In pratica ovviamente non viene sempre fatta la copia: viene utilizzata una politica di lazy-evaluation sulle copie in maniera da utilizzare la variabile originale fin tanto che non vengono fatte modifiche e di copiarla in una nuova variabile solamente a fronte di una richiesta di modifica della stessa (questo solamente per una questione di efficienza).

Ma è possibile ottenere in Matlab i side effects?

Ovviamente è possibile ottenerli utilizzando Java o creando MEX-files in C o in FORTRAN. E' però possibile ottenere i side effects anche in Matlab puro sfruttando i workspaces temporanei creati durante le chiamate a funzione. Nel post Programmare OOP in Matlab è stato spiegato come costruire una classe in Matlab utilizzando solamente le funzioni. Ora, si ipotizzi di istanziare la classe counter, descritta in quel precedente post, e crearne una copia come segue:
c1 = counter(1); % Istanziazione:
c2 = c1; % Copia:
Ora l'oggetto c1 e l'oggetto c2 sono esattamente lo stesso oggetto. Le modifiche su uno hanno side effects sull'altro, infatti:
c1.next()
ans = 1
c2.next()
ans = 2
c1.next()
ans = 3
c2.next()
ans = 4
Inoltre realizzando una funzione come la seguente:
function incrementa(c)
c.next();
E richiamandola come segue:
c =counter(1);
incrementa(c);
incrementa(c);
c.next()
ans = 3
E' possibile appurare che l'oggetto passato alla funzione può essere modificato dall'interno della stessa generando side-effects.

SPIEGAZIONE: Le classi realizzate come spiegato nel post precedente sfruttano la creazione di un workspace locale (WL) per ogni chiamata a funzione Matlab, quando una funzione Matlab viene richiamata un workspace temporaneo viene creato ex-novo in cui "vivono" le variabili locali della funzione, alla terminazione dell'esecuzione tale WL viene lasciato in pasto al garbage collector che normalmente lo rimuove, nel caso però in cui vengano restituiti i puntatori a funzioni innestate, che possono quindi accedervi, il WL non viene rimosso perchè esistono ancora delle variabili che vi possono accedere. Il WL viene eliminato quando anche l'oggetto istanziato diviene irraggiungibile. A differenza delle normali variabili però il WL è legato all'istanza dell'oggetto in maniera indiretta, non fa parte della variabile, questo significa che copiare la variabile non copia il WL. L'oggetto rappresenta in maniera indiretta un puntatore al WL, passare quindi questo "puntatore" a una funzione o copiarlo non provoca la replica del WL che rimane lo stesso e soffre quindi dei side-effects.

Questo comportamento non deve essere visto come un "baco" ma come una "feature": infatti è un modo efficace per ottenere i side-effects quando e se servono.

Nessun commento: