Qui cerco di unire due argomenti che sono stati trovati nello stesso tempo ma che non necessariamente sono correlati.
Mentre passavo il tempo a programmare qualcosina mi sono imbattuto in un problemino interessante, ho un set di stringhe che conosco a priori, c'è un modo pulito e semplice per creare un array di stringhe tutto allocato in stack? Sicuramente è un problema che molti non si pongono, ma Ada mi ha insegnato che quando è possibile, è sempre meglio allocare in stack.
In C si può raggiungere facilmente questo risultato con:
E fin qui tutto ok, è un array di stringhe allocato in stack. Come fare in Ada? Ho provato questa soluzione:
Errore del compilatore! Le stringhe non sono della stessa dimensione, l'unico modo per risolvere è porre uno spazio dopo Hello ("Hello ") in modo da equiparare le stringhe. Problema fastidioso, sopratutto quando si ha a che fare con stringhe di lunghezza varia.
Quando si allocano gli array i row hanno tutte la stessa dimensione, in C non possiamo dichiarare greet[2][]; ma solo greet[][2]; specificando dopo il numero di row (che non è la dimensione di ogni singolo row). Lo stesso problema c'è nei database: puoi inserire facilmente un'infinità di righe, ma aggiungere campi ad una riga è una procedura dispendiosa (infatti è un'operazione che può fare l'admin della tabella).
Tornando alle stringhe, il problema di prima non accade in C perché le stringhe sono NULL based e tutte le sue funzioni si fermano al primo NULL che incontrano, ma anche lì le row hanno tutte la stessa dimensione. In Ada le stringhe non sono NULL based, dato che per dichiararle/allocarle bisogna sempre specificare la lunghezza e gli access type non ci permettono di andare in zone non allocate (evitando i famosi segmentation fault).
Si, ma come risolvere questo fastidioso problema?
Googlando ho scoperto che questo problema non è insolito, anzi è molto comune. Molti linguaggi ad alto livello implementano i ragged array, che possono contenere row di dimensioni diverse. In C e in Ada si potrebbe emulare questo fatto dichiarando un puntatore a puntatore, o un array di puntatori, facendolo puntare a locazioni allocate dinamicamente o preallocate.
Proviamo quest'ultimo in modo che sia allocato in stack e non in heap:
Hello : aliased constant String := "Hello"
World : aliased constant String := "World!"
Ecco quello che volevo, ma l'attributo 'Access non è il massimo in fatto di efficienza e performance, e di sicuro non è il massimo dell'eleganza. Ed io vado matto per il codice elegante! L'unica soluzione è la memoria dinamica:
Mentre passavo il tempo a programmare qualcosina mi sono imbattuto in un problemino interessante, ho un set di stringhe che conosco a priori, c'è un modo pulito e semplice per creare un array di stringhe tutto allocato in stack? Sicuramente è un problema che molti non si pongono, ma Ada mi ha insegnato che quando è possibile, è sempre meglio allocare in stack.
In C si può raggiungere facilmente questo risultato con:
char *greet[2] = {"Hello","World!"};
E fin qui tutto ok, è un array di stringhe allocato in stack. Come fare in Ada? Ho provato questa soluzione:
Greet : array (1..2) of constant String (1..6) := ("Hello", "World!");
Errore del compilatore! Le stringhe non sono della stessa dimensione, l'unico modo per risolvere è porre uno spazio dopo Hello ("Hello ") in modo da equiparare le stringhe. Problema fastidioso, sopratutto quando si ha a che fare con stringhe di lunghezza varia.
Quando si allocano gli array i row hanno tutte la stessa dimensione, in C non possiamo dichiarare greet[2][]; ma solo greet[][2]; specificando dopo il numero di row (che non è la dimensione di ogni singolo row). Lo stesso problema c'è nei database: puoi inserire facilmente un'infinità di righe, ma aggiungere campi ad una riga è una procedura dispendiosa (infatti è un'operazione che può fare l'admin della tabella).
Tornando alle stringhe, il problema di prima non accade in C perché le stringhe sono NULL based e tutte le sue funzioni si fermano al primo NULL che incontrano, ma anche lì le row hanno tutte la stessa dimensione. In Ada le stringhe non sono NULL based, dato che per dichiararle/allocarle bisogna sempre specificare la lunghezza e gli access type non ci permettono di andare in zone non allocate (evitando i famosi segmentation fault).
Si, ma come risolvere questo fastidioso problema?
Googlando ho scoperto che questo problema non è insolito, anzi è molto comune. Molti linguaggi ad alto livello implementano i ragged array, che possono contenere row di dimensioni diverse. In C e in Ada si potrebbe emulare questo fatto dichiarando un puntatore a puntatore, o un array di puntatori, facendolo puntare a locazioni allocate dinamicamente o preallocate.
Proviamo quest'ultimo in modo che sia allocato in stack e non in heap:
Hello : aliased constant String := "Hello"
World : aliased constant String := "World!"
Greet : array (1..2) of access constant String := (Hello'Access,World'Access);
Ecco quello che volevo, ma l'attributo 'Access non è il massimo in fatto di efficienza e performance, e di sicuro non è il massimo dell'eleganza. Ed io vado matto per il codice elegante! L'unica soluzione è la memoria dinamica:
Greet : array (1..2) of access constant String := (new String'("Hello"), new String'("World"));
Ora ci siamo, ma sono rimasto sorpreso di una cosa, guardando il segmento text il codice è allocato in stack! Com'è possibile? Girando forum di Adaisti e poi approfondendo sul reference manual di Ada (avrò cercato su più di 500 pagine, sob): se l'operatore new è usato su un tipo access-to-constant e la dimensione è conosciuta in compile time, l'elemento viene allocato in stack.
La notizia è favolosa! Questa caratteristica permette parecchie ottimizzazioni, oggi che l'operatore new viene usato e straabusato. Credevo che lo slogan Ada is a self-optimizing language fosse solo una trovata pubblicitaria, mi ero sbagliato.
Sempre più contento della scelta di Ada.
La notizia è favolosa! Questa caratteristica permette parecchie ottimizzazioni, oggi che l'operatore new viene usato e straabusato. Credevo che lo slogan Ada is a self-optimizing language fosse solo una trovata pubblicitaria, mi ero sbagliato.
Sempre più contento della scelta di Ada.