mercoledì 26 febbraio 2014

Lo style puo' evitare bug?

Sono state spese molte parole sull'incidente di sicurezza della verifica dei certificati Apple in iOS, risolto tempestivamente con un aggiornamento dell'iOS da parte della casa madre (si veda qui e anche qui).
Il bug era, come spesso accade, banale: uno statement di troppo in una catena di "if" che causava l'interruzione della logica di valutazione dei condizionali. In pratica:

if ( condition 1 )
  goto fail;
if ( condition 2 )
  goto fail;
  goto fail; // <<< disaster!!!!!!
if ( condition 3 )
  goto fail;


fail:
  // something nasty happenend


Si potrebbe dire che era necessario maggiore testing, che si dovrebbero usare le parentesi di blocco per ogni condizionale, che non si dovrebbero usare i goto....ma secondo me la cosa principale che ha generato il bug nel codice in oggetto e' stata la mancanza dell'uso degli "else". Le condizioni in esame erano da considerarsi logicamente correlate, ossia:


if ( condition 1 )
  goto fail;
else if ( condition 2 )
  goto fail;
  goto fail;
else if ( condition 3 )
  goto fail;

che avrebbe generato un errore di compilazione per un "else" spoglio. Con questo non voglio dire che il compilatore deve essere usato per trovare gli errori, per quello ci sono i test. Ad ogni modo il bug e' emerso da un semplice problema di code-style e non di logica. Ancora meglio sarebbe stato scrivere:

if ( condition 1
    || condition 2
    || condition 3 )
    goto fail;

che avrebbe "logicamente" correlato tutte le condizioni di fallimento.
Questo bug rappresenta un esempio di come un code-style errato possa portare facilmente a errori banali, e si noti ancora una volta che il code style da adottare in questo caso non era tanto l'uso delle parentesi di blocco ma l'unione (con else o in un solo if) delle condizioni da testare.
E si noti anche che non sempre il compilatore e' in grado di segnalare il "code-unreachable": come riportato qui  GCC non implementa sempre questa funzione mentre CLANG la tiene disabilitata in default.

DevOps 2014

Ho partecipato con interesse all'incontro DevOps Italia 2014, che si e' tenuto la scorsa settimana a Bologna.

L'incontro e' stato ben organizzato e ben gestito: il clima era quello veramente DevOps con persone entusiaste delle metodologie agili e della loro applicazione alla tematica, ahimé spesso ostica, della cooperazione fra sviluppatori e sistemisti.
E' stata anche una buona occasione per rivedere amici di altre community e aziende.
Unica pecca organizzativa: la mancanza di alcuni contenuti. La conferenza infatti e' terminata abbastanza presto per la mancanza di ulteriori relatori, ma penso che questo si aun problema generalizzato al panorama IT nazionale degli ultimi anni. Noto infatti sempre piu' spesso come i colleghi nazionali si siano impigriti nella produzione di contenuti e nello scambio di conoscenza. Penso cio' sia dovuto anche al difficile momento economico, che forse spinge tutti-contro-tutti nella battaglia del lavoro e che si riflette in un cerco-di-tenere-quante-piu'-cose-per-me.

Ho apprezzato gli OpenSpace, vero momento di aggregazione fra i partecipanti, anche se alcuni di questi momenti si sono rapidamente tramutati in piccoli seminari o lezioni private. Ma ammetto che organizzare e gestire un open space "formalmente" corretto non e' cosa banale, e molto dipende anche dai partecipanti stessi.

Riepilogando un'esperienza positiva, e che consiglio a molti colleghi del panorama IT.

E per finire una nota dolente sugli speaker: le slide sono state in generale pessime per ogni oratore. Anzitutto noto sempre piu' spesso la mancanza di uno "standard" di produzione delle stesse: ogni speaker ne ha di differenti, spesso differenti anche dal talk tenuto poco prima. Capisco che non tutti vogliano usare LaTeX, e che non tutte le conferenze forniscano dei template ufficiali, ma trovo veramente seccante passare attraverso slide poco contrastate e con font piccoli a veri e propri cartelloni pubblicitari.
Ma ancora piu' seccante e' questo voler usare l'inglese per tutto il materiale. Credetemi, cari speaker, una slide introduttiva "Who I am" o "What I do" in una conferenza italiana non e' segno di maggiore professionalita', ma solo di volersi dare un tono anche quando non serve. Sicuramente c'e' il momento per scrivere e parlare inglese, come pure c'e' il momento per farlo in italiano. Uno speaker che non comprende a che conferenza e', e quindi non comprende il livello tecnico/linguistico della platea, non e' un buon speaker! Almeno questo e' il mio parere.

Scalare una lista in Perl (nel senso di applicare scalar!)

I contesti di invocazione di funzioni e operatori di Perl sono qualcosa di magico, e come ogni cosa magica non sempre funziona come ci si aspetterebbe. Qualche giorno fa una nota ha colpito la mia attenzione: l'uso dell'operatore scalar applicato ad una lista di liste.
Cerco quindi con questo articolo di chiarire un po' il concetto di "da lista a scalare" e "da scalare a lista".
Il passaggio da scalare a lista e' abbastanza facile: l'operatore ',' unito alle parentesi tonde permette di convertire una serie di scalari in una lista; e' inoltre possibile creare al volo liste di liste come ad esempio in:

my (($minute, $hour), ($day, $month, $year)) = (localtime())[1..5];

che, seppure privo di molto significato (poiche' si referenziano cinque scalari indipendenti) estrae due liste e assegna i singoli valori. La cosa e' equivalente a quanto segue:

my @time = (localtime())[1,2];
my @date = (localtime())[3,4,5];
my $minute = $time[ 0 ];
my $hour = $time[ 1 ];
my day = $date[ 0 ];
my month = $date[ 1 ];
my year = $date[ 2 ];

ma non equivalente a questa:

my ($minute, $hour, $day, $month, $year) = (localtime())[1..5];

che invece estrapola una lista sola assegnando i singoli valori come segue:

my @time_and_date = (localtime())[1..5];
my $minute = $time_and_date[ 0 ];
my $hour = $time_and_date[ 1 ];
my day = $time_and_date[ 2 ];
my month = $time_and_date[ 3 ];
my year = $time_and_date[ 4 ];

In un certo senso l'operatore ',' e' sovraccaricato: se valutato in contesto scalare rappresenta una continuazione del flusso di esecuzione (come in C), se in contesto di lista concatena gli elementi (scalari o no) in una lista.

L'operatore 'scalar' forza un contesto scalare dove c'e' un contesto di lista (ossia parentesi e virgola) annullando di fatto l'effetto delle parentesi e mutando il comportamento della virgola:

  • (,) viene valutato come virgola in contesto di lista
  • scalar (,) viene valutato come virgola in contesto scalare
  • scalar , viene valutato come virgola in contesto scalare

Ecco allora che il seguente semplice esempio:

#!/usr/bin/env perl -w

my (($minute, $hour), ($day, $month, $year)) = (localtime())[1..5];
$month++, $year += 1900;

print STDOUT "\nToday is $month / $day / $year at $hour:$minute\n";

print STDOUT "\n all variables as list: ", (($minute, $hour), ($day, $month, $year));
print STDOUT "\n all variables via scalar: ", scalar (($minute, $hour), ($day, $month, $year));


produce come output:

Today is 1 / 28 / 2014 at 13:48

all variables as list: 48132812014
all variables via scalar: 2014

Ossia la stampa della lista di liste produce, come ovvio, i valori concatenati, mentre la stampa 'scalar' della lista di lista produce la stampa del solo ultimo valore. In questo caso ogni operatore virgola viene trattato come continuazione del flusso di esecuzione. Da notare anche che la "lista di liste" è solo un fatto mentale: di fatto ogni espressione fra parentesi viene resa una lista piatta, e quindi non importa quante coppie di parentesi ci siano.
Da questo punto di vista l'operatore 'scalar' puo' essere pensato come un "anti-parentesi-di-lista". Da notare infatti che non conta quanto annidate siano le liste (ossia quante parentesi ci siano), l'espressione e' sempre valutata in contesto scalare come se fosse stata scritta senza parentesi.

La documentazione riporta in modo ben chiaro questo fatto:

Because "scalar" is a unary operator, if you accidentally use a parenthesized list for the EXPR, this behaves as a scalar comma expression, evaluating all but the last element in void context and returning the final element evaluated in scalar context. This is seldom what you want.

sabato 22 febbraio 2014

Vari linguaggi di programmazioen a confronto

Vi ricordate le pubblicità della Apple per lanciare il Mac? Beh, che abbiano fatto moda si sa, e quindi ecco l'ennesimo risultato: la comparazione dei linguaggi di programmazione! Ma ne manca uno particolare...anzi particolarmente importante, chissà perché....


mercoledì 19 febbraio 2014

Eliminare la freccia in Perl

Perl utilizza l'operatore '->' (freccia) per la dereferenziazione esplicita dei riferimenti.
Spesso accade che i neofiti di Perl restino confusi da quando l'operatore '->' puo' essere rimosso dalle espressioni. Si consideri il seguente esempio:

my $array_ref = [ [ qw(a b c)], [qw(1 2 3)] ];

say "The first cells are " . $array_ref->[0]->[0] . " and " . $array_ref->[1][0];

Non vi e' alcuna ragione per usare la doppia freccia, come riportato  nell'ultimo accesso al primo elemento del secondo array.
Ma perche'?
In Perl non e' possibile definire array di array, o piu' in generale, strutture dati complesse senza passare attraverso i riferimenti. Ne consegue che dopo la prima '->', che dereferenzia un riferimento, se ci si trova una espressione di indicizzazione Perl sa che deve trattarla come una ulteriore dereferenziazione.
Quando Perl trova $array_ref->[1] sa che deve trattarla come una dereferenziazione (operatore '->') seguita dall'accesso ad un array; se le cose si fermano qui tutto bene, ma se si aggiunge un altro accesso ad array (o hash) Perl sa per certo che questo e' possibile solo tramite riferimento, e quindi la dereferenziazione e' implicita.

mercoledì 12 febbraio 2014

KDE at work

E' stato pubblicato un interessante post sul planet di KDE che mostra alcuni screenshot del favoloso desktop Unix in azione in ambienti di produzione. Si tratta in particolare di due aziende che realizzano effetti speciali per film e serie televisive: Framestore e di The Mill.





Mostrare questi utilizzi del desktop del drago e' importante al fine di rendere ancora piu' esplicito il livello qualitativo del software OpenSource e del Plasma Workspace.

tail-call goto

In Perl l'istruzione goto ha diversi significati e utilizzi: oltre al "classico" salto verso una label infatti permette anche il salto verso una funzione da un'altra funzione. In questo caso avviene quella che viene spesso definita una tail-call, poiche' il salto rappresenta l'ultima istruzione eseguita sullo stack frame corrente.
In occasione del salto tail-call gli argomenti local vengono resettati e la funzione di destinazione viene invocata come fosse stata invocata individualmente rimuovendo lo stack attuale; i parametri @_ mantengono il loro valore attuale (ossia le modifiche sono propagate).
Si consideri il seguente esempio:

#!/usr/bin/env perl -w

use v5.10;

$value = 10;

sub foo{
say "Inside foo and the value is $value";
say join ", ", caller;
}

sub bar{
local $value = 20;
say "Inside bar and the value is $value";
goto &foo;
}


say "Let's start...";
say join ", ", caller;
say "...and now the magic!";
bar;


L'invocazione di caller serve a rendere visibile lo stack di chiamata, che nel caso del main e' assente.
L'invocazione di bar effettua una modifica a $value, e poi una tail-call verso foo. A questo punto Perl rimuove dallo stack i dati di bar (rimuovendo quindi la localizzazione di $value) e invoca foo come se fosse stata chiamata direttamente dal main. E infatti il programma produce il seguente output:

Let's start...

...and now the magic!
Inside bar and the value is 20
Inside foo and the value is 10
main, test.pl, 22

Da notare che l'output di caller produce un solo frame invocante, il main, anche se a prima vista foo() e' stata invocata tramite bar().
Da notare che il sigillo di subroutine e' obbligatorio per permettere a goto di comprendere che si tratta di un salto ad una funzione, non ad una label.

venerdì 7 febbraio 2014

Addio e grazie per tutto il pesce

Si chiude un'altra era..
La terza.


giovedì 6 febbraio 2014

= <> = (ossia quando un assegnamento non ha sempre lo stesso significato!)

In molti linguaggi C-like e' possibile concatenare istruzioni di assegnamento in una sola:

a = b = foo();

con il risultato che gli operandi a sinistra dell'ultimo simbolo '=' sono trattati tutti come lvalue e assegnati al valore rvalue simultaneamente, ovvero come se si fosse diviso l'assegnamento:

b = foo();
a = b;

In Perl la concatenazione degli assegnamenti potrebbe non seguire le stesse regole. O meglio, siccome in Perl e' lecito assegnare valori di tipo diverso fra loro, ogni operatore di assegnamento segue le regole del rispettivo lvalue. Per dimostrare questo fatto, tutto sommato semplice da capire ma che puo' rivelarsi molto subdolo, e' possibile considerare il seguente semplice programma:

#!/usr/bin/env perl -w

use v5.10;

sub foo{
return qw(Hello LIST World) if wantarray;
return "Hello World";
}


$scalar = foo();
@array = foo();

say "The scalar value is < $scalar >";
say "The array values are < @array >";

che produce l'atteso output che segue:

The scalar value is < Hello World >
The array values are < Hello LIST World >

Il trucco e' semplice e ben noto: in Perl ogni cosa avviene in un contesto specifico e wantarray e' capace di fornire il contesto di chiamata della funzione consentendo una sorta di sovraccarico del valore di ritorno.
Ma analizziamo un'assegnamento piu' complesso:

$scalar = @array = foo();

L'output prodotto e' il seguente:

The scalar value is < 3 >
The array values are < Hello LIST World >

Cosa e' successo?
Per prima cosa viene valutato il rvalue dell'espressione, ossia foo(): tale funzione viene chiamata in un contesto di lista poiche' il primo assegnamento del rvalue e' ad un array, e quindi @array diviene, correttamente, il contenitore della lista.
Successivamente @array viene assegnato a $scalar, ossia c'e' un assegnamento di lista in contesto scalare, e quindi si calcola la dimensione dell'array (3 appunto) e la si assegna a $scalar.
Una volta compreso questo, il seguente assegnamento produce lo stesso effetto finale su $scalar per ovvi motivi:

$scalar = () = foo();

E questo evidenzia come sia possibile mutare il comportamento delle funzioni forzando un contesto senza necessariamente passare per variabili temporanee.
Ma per cortesia, non scriviamo codice del genere (si pensi alla sanita' mentale degli altri programmatori che si troveranno davanti questa espressione)!

Minimal Emacs

Non so se si debba parlare di "evoluzione" o di "regressione", ma sempre piu' spesso mi accorgo di trovarmi a mio agio con le cose essenziali e minimali, senza troppe distrazioni.
Ed e' cosi' che nell'infinito processo di configurazione del mio Emacs sono giunto al minimo storico per quanto riguarda i gadgets:

(when (fboundp 'tool-bar-mode)
 (progn
  (scroll-bar-mode -1)
  (menu-bar-mode -1)
  (tool-bar-mode -1) ) )


ovvero rimozione della toolbar, della scrollbar e perfino della barra dei menu'. In sostanza ora Emacs appare come uno di quegli orribili terminali X con il minimo delle decorazioni possibili. Perche'? Beh, perche' cosi' facendo resta un sacco di spazio per il contenuto dei buffer, e dopotutto chi usa i menu' o la scrollbar?

sabato 1 febbraio 2014

What do you think about Apple?

Chi mi conosce sa che non sono un fan della Apple, per svariati motivi che prima o poi elencherò. Nel frattempo penso sia interessante sentire cosa ne pensa Larry Wall, inventore di Perl circa Apple e i brevetti sul software.