Newsgroup: it.comp.lang.c++
Titolo: ottimizzazioni

Spero di non essere OT!
Secondo voi c'e' differenza tra le ottimizzazioni di un compilatore rispetto ad un altro?
Se doveste creare un'applicazione la cui velocita' di esecuzione e' fondamentale,
cosa usereste tra GCC, VisualC++6, VisualC++ 2005 Express Edition?
ciao 

 cosa usereste tra GCC, VisualC++6, VisualC++ 2005 Express Edition?
Fino a qualche anno fa la situazione era questa: Il compilatore
dell'Intel ottimizzava meglio di quello Microsoft che, a sua volta,
ottimizzava meglio del gcc. In particolare mi ricordo che il gcc aveva
seri problemi a sfruttare le operazioni SSE e SSE2 (in alcuni casi il
codice prodotto era piu' lento invece che piu' veloce).
Ora credo che il gcc abbia fatto buoni passi avanti, ma la mia e' una
supposizione basata solo su una serie di notizie riguardanti i buoni
progressi fatti dal gcc nel campo delle ottimizzazioni.
In definitiva penso che il compilatore del VisualC++ 2005 crei codice
un po' piu' veloce o, al limite uguale, di quello prodotto dal gcc. Il
compilatore del VisualC++ 6 fuggilo come la peste visto che e' molto
distante dall'essere un compilatore C++ standard.
Comunque considera che difficilmente si risolvono i problemi di
lentezza di un software semplicemente utilizzando un compilatore piu'
performante. Cambiando compilatore puoi guadagnare se ti va bene un
10%-20% (la butto li') in velocita', cambiando algoritmo puoi
guadagnare diversi ordini di grandezza.
Saluti,
The Librarian

guadagnare diversi ordini di grandezza.
...cambiando sistema di sviluppo in generale, affidandosi alla
compilazione JIT, magari si guadagna ancora di pių, compilando,
all'occorrenza, per il processore specifico ;-)

 ha scritto nel messaggio 
news:47571e6d$0$36442$4faf...@reader5.news.tin.it...


 cosa usereste tra GCC, VisualC++6, VisualC++ 2005 Express Edition?
Ottimizzerei l'algoritmo.

 all'occorrenza, per il processore specifico ;-)
Ho dei seri dubbi a riguardo, anche se, ammetto, più per sensazione che
per esperienza.
In ogni caso, la strada non è l'ottimizzazione del codice, ma
dell'algoritmo di base. (leggi: complessità computazionale).

 all'occorrenza, per il processore specifico
Onestamente sono sempre rimasto perplesso su queste affermazioni. Un 
JIT deve compilare in un tempo "accettabile", mentre il compilatore, se 
gli dici espressamente che deve compilare per la CPU xyz, può metterci 
tutto il tempo che vuole, almeno in teoria. Poi il suo eseguibile 
magari non funziona su altri processori, e questo può non essere 
accettabile.
Non le basi per dire di avere ragione o torto, però.
E' una sensazione.
Comunque la cosa bella sarebbe avere delle misure; il programma xyz, 
che so un kernel, di quanto cambia abilitando le ottimizzazioni 
z1,z2,z3, oppure assumendo programmatori migliori, oppure facendo meno 
pressioni sui programmatore per avere il prodotto ieri, oppure 
abbandonado definitivamente java? :-)

 definitivamente java? :-)
Perché? java è il più bel linguaggio del mondo!!! :-P

 dell'algoritmo di base. (leggi: complessità computazionale).
Beh, è ovvio che cambiando l'algoritmo, cambiano le carte in tavola.
Pensavo si stesse ragionando, nello specifico, sulle capacità di
ottimizzazione del compilatore.

 abbandonado definitivamente java? :-)
+1 su tutto. Specialmente sull'ultimo punto :-)
Dopo due anni di sviluppo in Java ho voglia di impiccarmi.

 Perché? java è il più bel linguaggio del mondo!!! :-P
Pensa che c'è chi lo crede sul serio!

 ottimizzazione del compilatore.
Si e no :) ed infatti la mia prima risposta è stata semplicemente che se
il problema è specifico di performance, la primissima strada non è
quella di cambiare compilatore ma di ottimizzare il codice :-)
(anche sulla base del compilatore usato, a dire il vero)

 Queste verranno tradotte in altrettanti istruzioni cpu:
<snip>
Non necessariamente. Sarebbe una traduzione che prescinde
dall'ottimizzazione.
Ottimizzare significa, presumibilmente, tradurre quelle istruzioni in
un'unica istruzione di swap.
Non ci vedo una gran differenza tra tradurre direttamente da codice
sorgente e tradurre da una qualsiasi forma di codice oggetto.
Comunque il punto fondamentale che mi premeva sottolineare è che,
mentre con un compilatore tradizionale, riesci a compilare per una
piattaforma generica, con una compilazione "ritardata" riesci ad
allinearti all'hardware specifico e questo, almeno sulla carta, è un
vantaggio no da poco.

 vantaggio no da poco.
Si, su questo non ci piove. Infatti sono un estimatore (per certi versi)
di gentoo, che fonda la sua esistenza proprio su questo paradigma.
Quel che a me lascia perplesso, invece, è il passaggio per il bytecode.
Tutto li'. L'esperienza del gcj recentemente avuta mi da' da pensare,
anche se non sono ancora sicuro della mia interpretazione alla cosa...

 Perché? java è il più bel linguaggio del mondo!!! :-P
Penso male di Java e penso bene di Python, dal punto di vista delle 
prestazioni. E' più forte di me. Lo so che magari sono preconcetti, ma 
non ce la posso fare.

 un soffio.
Un programma dotnet, come un tempo i programmi in VB, partono 
abbastanza in fretta. E' questo la cosa che mi lascia perplesso. In C++ 
ci metto minuti a compliare, e in dotnet tutto si risolve in una 
manciata di secondi? Però non avendo mai fatto dei test, mi tengo 
questi dubbi dentro di me, in un angolo buio.

 non ce la posso fare.
Non so, ho studiato da poco java dopo anni ed anni di C++. Java ha delle
caratteristiche senz'altro interessanti, altre terribili (generics?)...
Mi piacerebbe vedere nella prossima versione del c++ le cose buone del
java che l'attuale c++ non ha.

 Si, molto. Diciamo che per gcc la scelta di -O2 è quella migliore.
Occhio che se O2 va bene per il C, di sicuro non e` una buona idea x il 
C++ in quanto ci vuole O3 perche` vengano effettivamente risolte inline 
le funzioni inline o definite all'interno dell'header, con -O2 in 
pratica rischi di fare dei salti e reimpostare stack pointer e registri 
per ognuno dei vari getters/setters di cui sono piene tutte le classi, 
scrivo rischi perche` non sono sicuro se con -O2 cose semplici tipo:
int Width() { return m_width; }
Vengano comunque portate in linea.
--
Bye,
  Gabry

 le funzioni inline o definite all'interno dell'header, 
Buono a sapersi, proverò a guardare.

 le funzioni inline o definite all'interno dell'header
Scusami, sei sicuro?
Io ho sempre pensato che le funzioni inline venissero considerate per
essere messe inline e che -finline-funciton servisse a dire al
compilatore di provare a mettere inline qualsiasi funzione (anche non
inline) sotto una certa dimensione.
Ho dato un'occhiata alla documentazione e dice:
<quote>
-finline-functions
Integrate all simple functions into their callers. The compiler
heuristically decides which functions are simple enough to be worth
integrating in this way.
</quote>
Quando dice "all simple functions" io credo si riferisca anche a
funzioni non inline e definite nel corpo della classe.
Saluti,
The Librarian

 pensiero) ad un "coso" che compila mentre fa l'instalalzione ....
Non so se c'entra qualcosa, ma c'è una distribuzione GNU/Linux che ti 
compila il codice dai sorgenti quando installi i pacchetti... ora non mi 
viene il nome... ma mi sa che non ha avuto molto successo.
E.

 viene il nome... ma mi sa che non ha avuto molto successo.
Mi sa che ce ne sia anche piu' di una.
Al di la' dei benefici di una compilazione su misura, molti non si 
fidano dei binari precompilati e ricordo di aver letto in qualche 
manuale che non si e' "veri amministratori" se non ci si compila le 
applicazioni da soli :-)
Personalmente (su FreeBSD) uso questo metodo (anche se per altri motivi).
  bye
	av.

 Edition?
intel. fra gli altri direi che cercherei di scrivere codice decoroso e
ben pensato, poi userei l'ambiente con cui mi trovo meglio.
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.

 prestazioni molto, molto diverse (quasi due ordini di grandezza!)...
1. gcj immagino che lo stai usando per creare bytecode, se lo usi per
compilare il discorso ha poco senso.
2. la macchina virtuale java è *estremamente* lenta a caricarsi.
dovresti fare esperiementi con codice che fa veramente calcoli. ma ti
anticipo.
<
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=java&
lang2=gpp>
Come vedi al momento attuale sul calcolo puro g++ è *effettivamente* più
performante di Java. Con il problema che fare un benchmark di hotspot
non è banale e un metodo più è chiamato e più è probabile che sia
ottimizzato.
Ma per darti un idea già comparando ad ADA (sempre su piattaforma
libera), la differenza si riduce.


 java che l'attuale c++ non ha.
tipo?


 questi dubbi dentro di me, in un angolo buio.
Beh, intanto C++ è particolarmente pesante da compilare per una serie di
ragioni che prescindono dall'ottimizzazione. Se per dire lo compari con
FreePascal c'è un'abisso in termini di 'quanto ci mette per essere
compilato'.
In secondo luogo per la regola del 20-80 (che per alcuni è 10-90) tu
veramente vorresti che solo il 20%(10) del tuo codice sia compilato e
ottimizzato. Per il resto cambia quasi nulla. 
Non solo, in effetti anche in quel 20% di codice ci sono pezzi della cui
ottimizzazione potresti impippartene (leggi gestori di eccezioni
'rari'). 
Ecco Java non fa l'ultima ottimizzazione, ma sicuramente se un metodo è
chiamato di rado non lo ottimizza. Ottimizza solo quelli chiamati spesso
(e possibilmente con informazioni sul call site tipico che possono
attivare altre ottimizzazioni non disponibili al compilatore).
*Adesso* la compilazione aot è sicuramente vincente a livello di
prestazioni. Non solo, la maggior parte dei linguaggi compilati sono
stati *pensati* per essere più efficienti (che so, in Java tutti i
metodi sono 'virtual' per dirla alla C++, quasi tutta la roba non banale
è nello heap, etc etc etc). Probabilmente fra non troppo chi scrivesse
un linguaggio pensato per essere Jittato potrebbe ottenere performance
migliori. Certo, ormai la tendenza è verso linguaggi come Python e Ruby,
perchè la cosa più importante è scrivere codice corretto e mantenibile e
per le parti che devono essere veloci si può sempre ricorrere a C/C++ e
quant'altro.


 migliori.
Ieri uno dei PC a casa, dopo avere scaricato le patch per dotnet 2.0 e 
3.0 è restato per lungo tempo catatonico. Il S.O. ha ricompilato 
l'universo con uso del 100% della CPU. Questo mentre io cercavo con 
urgenza una ricetta per le crep. Le crep mi sono venute uno schifo per 
colpa del JIT :-[


Talismano della felicita' - Google 1 - 0 ;-)
Ciao,
Nicola

 colpa del JIT :-[
Concludiamo: le crep vanno compilate ahead of time. :P


 Concludiamo: le crep vanno compilate ahead of time. :P
Dimenticavo, giusto per pignoleria:
crêpes
Salut,
Nicola

 crêpes
Quelle buone.
Le mie erano crep. Nemmeno una pallida copia di quelle originali.

 performante di Java. 
E' quello che interessava me, effettivamente: Sviluppare un modello
matematico in C++ o in Java? Questa era la domanda!


Il Java si e' dimostrato molto efficiente nelle operazioni
matematiche.
Detto questo un programma C++ scritto come dio comanda magari ha
prestazioni migliori.
Tieni presente comunque che anche attualmente una buona parte dei
motori grafici per videogame 3D sono scritti in C :) ( non c++ )
Daniele

 motori grafici per videogame 3D sono scritti in C :) ( non c++ )
Sì? Questo mi sembra molto strano... il C++ è molto comodo per gestire 
le strutture e i modelli 3D. A meno che non ti riferisci alle librerie 
di interfaccia con l'hardware, come le OpenGL (e credo anche le DirectX) 
che sono scritte in C per avere il massimo grado di utilizzabilità (le 
librerie C possono essere linkate in credo tutti i linguaggi).
E.

 matematico in C++ o in Java? Questa era la domanda!
La risposta mia č che qualunque cosa possa fare in un linguaggio
differente da Java la faccio in tale linguaggio.
Java ha *eccellenti* tool di sviluppo (fra i migliori e fra gli open
source i migliori). Tuttavia come linguaggio mi mette tristezza, per cui
potendo...
Ad ogni modo io un modello matematico computazionalmente pesante lo
svilupperei in C++ o in OCaml a seconda del *tipo* di computazioni.
Tipicamente per maneggiare cose principalmente simboliche OCaml č
abbastanza avvantaggiato (anche se fra tutti gli imperativi con la
potenza dei templates si scavallano molte noie pure in C++). 
C++ č un ottimo linguaggio per andare forte. 
Ma Java non va male, dipende cosa devi farci. Io personalmente farei il
nucleo duro e puro in C++ e poi lo strato superiore in Python.
Cosě ho flessibilitŕ avvicinandomi all'utente e velocitŕ avvicinandomi
al nucleo.


 motori grafici per videogame 3D sono scritti in C :) ( non c++ )
In linea di principio Java parte svantaggiato rispetto a C++, perche'
paga sia il passaggio per il bytecode, ovvero la compilazione al volo,
che un supporto runtime decisamente piu' pesante.
Altrettanto in linea di principio la compilazione al volo e'
avvantaggiata rispetto alla compilazione anticipata perche' puo'
attingere informazioni dallo stato effettivo in cui avviene
l'elaborazione. Per contro esiste l'ottimizzazione guidata dalla
profilazione che puo' compensare la situazione, senza contare che,
ancora una volta in linea di principio, la compilazione anticipata
puo' anche durare giorni se ne vale la pena, mentre la compilazione al
volo vive sotto il vincolo che la somma del tempo di compilazione piu'
il tempo di esecuzione del codice compilato sia inferiore del tempo di
esecuzione del codice bytecode interpretato.
Si potrebbe aggiungere che Java e' piu' semplice da compilare del C++,
per cui a parita' di risorse ne resta di piu' da investire
nell'ottimizzazione. D'altra parte l'approccio tradizionale del C++ e'
piu' efficiente nell'utilizzo delle risorse di calcolo in presenza di
piu' esecuzioni parallele dello stesso programma.
Alla fine della fiera contano di piu' gli strumenti di contorno,
dall'hardware al compilatore alla macchina virtuale, ed il modo di
utilizzarli, che non le caratteristiche del linguaggio.
Ciao,
Nicola

 utilizzarli, che non le caratteristiche del linguaggio.
Quoto. Ma non dimentichiamo che tutt'ora per parti *veramente*
computazionalmente intensive l'uso di asm è un must, figuriamoci la
computazione nativa.
Un esempio? Quando presi il mio iMac Intel (Core Duo) GMP non poteva
fare uso dell'ottimizzazione in asm (e tutt'ora su OS X Intel 32 bit mi
pare non sia abilitato). In queste condizioni il mio portatile con un
'vecchio' G4 (con anche limiti più seri al bus, disco lento, etc) non
veniva stracciato. Aggiungo inoltre che GMP non è particolarmente
ottimizzata su G4. Ecco. Poi in GMP sono scritte in asm una manciata di
funzioni, mica tutto, chiaramente.
Poi io nutro forti speranze nel JIT. Ma al momento attuale non ci sono
santi. 


 computazione nativa.
In che senso, scusa? Al di là della portabilità, difficilmente un
programmatore umano in asm potrebbe far meglio di un compilatore nativo
per un dato processore (esempio: ottimizzazioni per la branch
prediction, per l'ottimizzazione delle pipeline, per la
parallelizzazione somma/prodotto, eccetera).
Credo non intendessi questo.

 programmatore umano in asm potrebbe far meglio di un compilatore nativo
Su questo non ci giurerei. Le istruzioni "multimediali" che lavorano su 
più dati contemporaneamente non so se sono gestite "bene" dal 
compilatore. Anche perché come fai a descrivere in C/C++ un algoritmo 
che lavora su 4 byte/int/quel_che_è contemporaneamente?

 che lavora su 4 byte/int/quel_che_è contemporaneamente?
In che senso? in assembly è facile, se sai l'esatto comportamento delle
istruzioni (e il compilatore lo sa meglio di tutti), cambiarne l'ordine,
il classico, per esempio, è del branch prediction:
	jnz $address
	cmp %eax, %ebx
non so oggi ma ai tempi dei primi pentium questa sequenza era più
vantaggiosa, in termini di performance, rispetto quella logica di
confronto (cmp) e salto condizionato (jnz), per il fatto che la jnz
richiedeva un ciclo di fetch in più che veniva guadagnato spostando
temporalmente l'istruzione stessa prima del confronto.
Idem per l'esecuzione in parallelo di più somme o somme e prodotti
(esistono istruzioni composte di prodotto più accumulo)... Insomma,
ottimizzare a mano oggi non è possibile.

 al nucleo.
Il python non lo conosco se non per sentito dire, so che ci sono dei
"cosetti" della telit che si programmano (guarda un po') in python e ciò
mi fa pensare ad una certa versatilità... Però mi da' da pensare il
fatto dei blocchi separati da indentazione, mi da' l'aria di essere un
modo poco preciso (anche se obbbliga al rigore)...

 tipo?
La prima cosa che mi ha affascinato (anche se sul momento la trovavo
inutile) erano le classi anonime. Non ho ancora fatto il passo di
verificare se in C++ è possibile realizzare qualche cosa di analogo
(sono rimasto un po' indietro nei costrutti, effettivamente)...
I template invece li trovo troppo rigidi, il controllo in compilazione è
in certi casi troppo limitativo. A questo preferirei un meccanismo alla
generics del java, ma a quanto pare è stato realizzato in modo
vergognoso (parlo per ciò che ho letto, ho troppo poca esperienza in
merito per essere attendibile).

 Cos'hanno di diverso rispetto delle normali istruzioni?
Somma 4 interi non lo esprimi con una istruzione in C/C++. Dimmi quali 
byte sono diversi da zero non lo esprimi con una istruzione. Tutto qui. 
Poi un tempo non c'era il problema che entrare in modalità "estesa" 
delle istruzioni costava tempo perché i registri sono sempre quelli?
Comunque non scrivo codec, per quel che faccio io non ho vantaggi nel 
conoscere le istruzioni del processore. Sono ignorante in materia.
-- 
Un libro da pausa caffè: 
http://research.microsoft.com/~daniel/uhh-download.html

 Pensa che c'è chi lo crede sul serio!
Diciamo che non è male, si può migliorare in molti aspetti, come tutto.
C'è anche chi crede che il migliore sia il perl (praticamente, l'unico
linguaggio write-only).

 modo poco preciso
Personalmente non mi da problemi. Almeno si è messo ordine a troppi 
stili di codifica che si sono stratificati nel tempo in C. Questo rende 
più leggibile il codice altrui.


 conoscere le istruzioni del processore. Sono ignorante in materia.
Oh, anche io. Al massimo mi dedico a dsp molto semplici o al firmware
delle fpga...

 
Ti faccio un esempio che conosco bene:
nell'image processing si ha a ce fare con operazioni "particolari" 
eseguite su matrici (le immagini).
Prendiamo ad esempio gli operatori "puntuali" (lavorano pixel a pixel): 
quando esprimi l'algoritmo in C o C++, scrivi in pratica un ciclo (o 
doppio ciclo) che itera su ciascun pixel, e per quel pixel scrivi il 
codice per elaborarlo. Vedi sotto l'esempio di somma px a px tra due 
immagini.
Nelle CPU moderne esistono delle estensioni "multimendiali" (da MMX a 
SSEx) che in una sola istruzione ti elaborano un tot di pixel in parallelo.
Un compilatore (ad oggi) non riesce a "capire" quale estensione deve 
usare perchè dovrebbe fare uno sforzo notevole per capire la semantica 
dell'operazione che stai eseguendo su ogni pixel e riorganizzare i cicli 
di scansione delle immagini per usare l'estensione (o la combinazione di 
estensioni) opportune.
Per un compilatore di oggi è troppo: tant'è vero che l'unica via per 
trarre vantaggio dalle istruzione estese è o scriversele a manina in asm 
(o più semplicemente quasi tutti i compilatori moderni ti permettono di 
usarle come "intrinsic" vedi 
http://msdn2.microsoft.com/en-us/library/y0dh78ez(VS.80).aspx
 ) o usare 
una libreria ottimizzata (scritta a manina in asm...). Vedi per esempio 
la libreria INTEL IPP che guadagna per certe operazioni di un fattore 20 
rispetto al codice "C ottimizzato" (e nota che il compilatore intel 
ottimizza parecchio bene).
Ad esempio:
somma due immagini costituite da pixel di 8 bit unsigned "con 
saturazione" ( se la somma eccede 0xFF, saturo il pixel con 0xFF)
in c avrai circa:
BYTE* pPx1;
BYTE* pPx2;
BYTE* pPxSum;
int temp;
for(y=0; y<cy; ++y)
{
pPx1 = Img1.GetPixel(y,0);
pPx2 = Img2.GetPixel(y,0);
pPxSum = ImgSum.GetPixel(y,0);
for(x=0; x<cx; ++x)
{
temp = *pPx1 + *pPx2;
if(temp > 0xFF) temp = 0xFF;
*pPxSum = (BYTE)temp;
++pPx1;++pPx2;++pPxSum;
}
}
con le SSE c'è unistruzione che si chiama PADDUSB che in un sol colpo ti 
somma 16 bytes consecutivi considerandoli unsigned e facendo la saturazione.
Prova a scrivere uno "pseudocodice" che la usa e vedrai che assomiglia 
poco al codice che ti ho messo sopra (anche perchè ti devi gestire 
alcuni px di "padding" per rientrare nell'allineamento corretto + altri 
problemini...)
GM

 parallelizzazione somma/prodotto, eccetera).
Dipende dal programmatore. Ci sono persone che hanno precisamente come
skill quella di ottimizzare pezzi di codice. In generale un umano sa
fare dimostrazioni di correttezza che gli ottimizzatori *non* sanno
fare. Come ti facevano notare, tipicamente per quanto riguarda
istruzioni vettoriali, parallelizzazione etc.
Il fatto è che gli umani *normali* a fare ste cose sbagliano di brutto.
Ma ci sono persone che hanno quest'abilità. 
Non mi credi? Fai le prove. Prendi gmp, mettila su un AMD, compilala
*senza* usare le ottimizzazioni in ASM, compilala usando le
ottimizzazioni in ASM e guarda i risultati.
Come fanno? Non ne ho idea. Tipicamente sulla mia esperienza
(programmando in asm su PPC) riesco frequentemente a battare il
compilatore in termini di compattezza del codice generato (in
particolare il mio algoritmo per scegliere i registri è migliore di
quello del compilatore). Non solo: io posso fare assunzioni che il
compilatore non può fare (esempio, una funzione che so che verrà
chiamata solo in determinate circostanze e solo da roba mia, per cui
scavalco bellamente alcune convenzioni dell'ABI).  Poi io sono un
dilettante assoluto e in generale non riesco a batterlo in velocità (o
meglio, il mio codice è più piccolo e comparabile - o marginalmente più
veloce - di quello ottenuto con -Os, ma nettamente più lento di quello
ottenuto  con -O3). 
Il principale problema è che non capisco nemmeno perchè il codice
generato dal compilatore sia più veloce del mio (il che è
controintuitivo, se li guardi a sboccio sembrerebbe più efficiente il
mio). Sapendo dove sta il problema, saprei anche risolverlo su piccole
funzioni.


 merito per essere attendibile).
No, assolutamente no. I generics di Java sono ridicoli: non sono
qualcosa di equivalente ai templates di C++. Sono una pezza ad un buco
grosso come una casa del modello di tipizzazione di Java. Ovvero menarla
all'inverosimile con la tipizzazione forte e poi essere costretti a
perdere tutte le informazioni di tipo quando si sbatte qualcosa dentro
un contenitore. Estraendolo si fa un bel cast a runtime. In pratica si è
bellamente cacciato nel cesso i (presunti) vantaggi della tipizzazione
statica. Allora nascono i generics.
I templates di C++ sono una feature di una potenza *inaudita*. E sono
tutto meno che limitativi.


 modo poco preciso (anche se obbbliga al rigore)...
Tutt'altro: è un metodo *estremamente* preciso. Poi non è che io starei
male per un 'end' in fondo. Ma complessivamente mi ci trovo benissimo.


 piů leggibile il codice altrui.
Quoto.


 linguaggio write-only).
Guarda, io Perl non lo reggo. Ma come tutto, dipende da chi lo scrive.
