Marco Cantù
|
Capitolo 2
|
Prima di passare alla scrittura di codice Pascal, e' importante sottolineare alcuni elementi di stile di programmazione Pascal. La questione che vorrei affrontare e' questa: A parte le regole di sintassi, come scrivere il codice? Non esiste una singola risposta a questa domanda, visto che le preferenze personali generano diversi stili. Comunque ci sono alcune regole da seguire riguardo ai commenti, maiscole, spazi e la cosidetta pretty-printing. In generale l'obbiettivo di ogni stile di programmazione e' la chiarezza. Le decisioni di formattazione, che si prendono sono una forma di stenografia indicante la funzione di un dato pezzo di codice. Un essenziale strumento per la chiarezza e' la coerenza ovunque dello stile che si sceglie, quindi assicurarsi di seguirlo attraverso tutto il progetto.
In Pascal, i commenti sono racchiusi tra parentesi graffe o parentesi tonde seguite da un asterisco. Delphi accetta anche i commenti nello stile C++, che si possono mettere anche alla fine di una riga:
{this is a comment} (* this is another comment *) // this is a comment up to the end of the line
La prima forma e' la piu' breve e la piu' usata. La seconda forma e' spesso preferita in Europa visto che diverse tastiere Europee non hanno il simbolo della parentesi graffa. La terza forma di commento e' stata presa dal C++ ed e' disponibile soltanto nelle versioni di Delphi a 32 bit. I commenti alla fine della linea sono di grande aiuto per brevi commenti e per commentare una specifica linea di codice.
Nota: Nei listati di questo libro cerchero' di scrivere i commenti in corsivo (e le keyword in grassetto), per essere consistente con i settaggi della sintassi in Delphi.
Avere tre differenti tipi di commenti puo' essere d'aiuto per costruire commenti nidificati. Se si cerca di commentare diverse righe di codice per disabilitarle e queste linee contengono gia' alcuni commenti, non si puo' usare lo stesso stile di commento:
{ ... code {comment, creating problems} ... code }
Con un secondo stile di commento, si puo' scrivere il seguente codice corretto:
{ ... code //this comment is OK ... code }
Da notare che se la parentesi graffa o la parentesi-asterisco e' seguita dal simbolo del dollaro ($), essa diventa una direttiva del compilatore, come in {$X+}.
Nota: Attualmente, le direttive del compilatore sono ancora commenti. Ad esempio, {$X+ Questo e' ancora un commento} e' valido. E' sia una valida direttiva sia un valido commento, anche se un buon progammatore tendera' probabilmente a separare direttive e commenti.
Il compilatore Pascal (diversamente da altri linguaggi) ignora la capitalizzazione dei caratteri. Di conseguenza, gli identificatori Myname, MyName, myname, myName, e MYNAME sono esattamente equivalenti. Nel complesso cio' e positivo, visto che nei linguaggi case-sensitive, diversi errori di sintassi sono causati da un'errata capitalizzazione.
Nota: C'e' solo un'eccezione in Object Pascal: La procedura di registrazione di un componente Register deve sempre cominciare con la R maiuscola, a causa di problemi di compatibilita' con C++ Builder.
Ci sono comunque leggeri inconvenienti. Primo, bisogna comprendere che questi identificatori sono veramente gli stessi, bisogna quindi evitare di usarli come elementi diversi. Secondo, bisogna tentare di essere coerenti nell'uso del maiuscolo per aumentare la leggibilita' del codice.
Una coerenza nell'uso del maiuscolo non e' forzata dal compilatore, ma e' buona abitudine seguirla. Un comune approccio e' quello di mettere maiuscolo solo il primo carattere di ogni identificatore. Quando un identificatore e' formato da diverse parole (non si possono inserire spazi in un identificatore), ogni prima lettera di ogni singola parola va in maiuscolo:
MyLongIdentifier MyVeryLongAndAlmostStupidIdentifier
Altri elementi ignorati dal compilatore sono spazi, a capo e tabulazioni inseriti nel codice sorgente. Tutti questi elementi sono conosciuti come spazi bianchi. Gli spazi bianchi sono usati per aumentare la leggibilita' del codice e non influenzano la compilazione.
Diversamente dal BASIC, il Pascal permette di scrivere un'istruzione composta da diverse linee di codice, dividendo una singola istruzione su due o piu' righe. L'inconveniente (almeno per i programmatori BASIC) di permettere istruzioni su piu' righe, e' che bisogna ricordare di terminarle con un punto e virgola. Da notare che la sola restrizione a questa regola sono le stringhe letterali, le quali non possono continuare su diverse linee.
Non ci sono nemmeno regole prefissate per l'uso di spazi bianchi e istruzioni multi-riga, soltanto alcuni consigli:
L'ultimo suggerimento sull'uso degli spazi bianchi in relazione alla formattazione del codice Pascal e' conosciuta come pretty-printing. La regola e' semplice: ogni volta che si deve scrivere un'istruzione composta, rientrare di due spazi a destra. Un'istruzione composta nidificata in un'altra istruzione e' rientrata di quattro spazi e cosi' via:
if ... then statement; if ... then begin statement1; statement2; end; if ... then begin if ... then statement1; statement2; end;
Nota: La formattazione sopra e' basata sulla pretty-printing, ma i programmatori danno differenti interpretazioni a questa regola generale. Alcuni programmatori rientrano le istruzioni begin-end al livello del codice interno, altri rientrano il begin-end ed anche il codice interno, altri infine mettono il begin sulla stessa riga dell'if. Questa e' una questione solo di gusti personali.
Un simile formato rientrato, e' spesso usato per le liste di variabili o tipi di dato e per continuare un'istruzione dalla precedente riga:
type Letters = set of Char; var Name: string; begin { long comment and long statement, going on in the following line and indented two spaces } MessageDlg ('This is a message', mtInformation, [mbOk], 0);
Ovviamente queste convenzioni vuogliono solo essere un suggerimento per rendere il codice piu' leggibile agli altri programmatori, visto che sono completamente ignorate dal compilatore. Ho cercato di usare queste convenzioni in tutti gli esempi e frammenti di codice di questo libro. I sorgenti di Delphi, i manuali e gli esempi inclusi nell'help in linea usano uno stile di formattazione simile.
Per rendere piu' facile la lettura e la scrittura del codice Pascal, l'editor di Delphi ha una funzionalita' chiamata color syntax highlighting. In relazione al significato che assumono, le parole scritte nell'editor, sono visualizzate usando differenti colori e stili. Di default le parole riservate sono in grassetto, le stringhe e i commenti sono colorate (spesso in corsivo) e cosi' via.
Le parole riservate, i commenti e le stringhe sono probabilmente i tre elementi che beneficiano maggiormente di questa funzionalita'. Si possono immediatamente vedere le keyword digitate non correttamente, le stringhe non terminate e la lunghezza dei commenti multi-linea.
Si possono facilmente personalizzare i settaggi della colorazione della sintassi usando la pagina Editor Color della finestra di dialogo Environment Options (vedere Figura 2.1). Se si lavora in gruppo con altri programmatori bisogna optare per i settaggi di default. Trovo infatti che lavorare su un computer con un diverso schema di colori e' veramente difficile.
Figura 2.1: La finestra di dialogo usata per cambiare i settaggi.
Nota: In questo libro ho tentato di applicare una sorta di sintassi colorata ai listati. Spero che risulti piu' leggibile.
Delphi 3 ha introdotto una nuova funzionalita' riguardo la scrittura del codice sorgente. Siccome nella scrittura di istruzioni in linguaggio Pascal spesso si ripetono le stesse sequenze di keyword, Borland ha messo a disposizione un nuovo strumento chiamato Code Template. Un code template e' semplicemente un pezzo di codice richiamabile con un testo chiave. Si digita il testo chiave, si preme Ctrl-J ed il pezzo di codice appare. Ad esempio scrivendo arrayd e premendo Ctrl-J, l'editor di Delphi espandera' il testo in:
array [0..] of ;
Siccome i code template predefiniti normalmente includono diverse versioni dello stesso costrutto, il testo chiave termina con una lettera indicante la versione alla quale si e' interessati. Comunque si puo' scrivere anche la parte iniziale del testo chiave. Per esempio se si scrive ar e si preme Ctrl-J, l'editor visualizzera' un menu con una lista di scelte disponibili con una breve descrizione, come si puo' vedere in Figura 2.2.
Figura 2.2: Selezione dei Code Template
Si possono completamente personalizzare i code template, modificando quelli gia' esistenti oppure aggiungendo nuovi pezzi di codice. In questo caso ricordarsi che il testo del code template generalmente include il carattere '|' per indicare dove si posizionera' il cursore ad operazione conclusa, ovvero, dove si parte a scrivere per completare il code template con il proprio codice.
Una volta definiti gli identificatori, si possono usare per costruire istruzioni ed espressioni che fanno parte di altre istruzioni. Il Pascal offre diverse istruzioni ed espressioni.
Le keyword sono identificatori riservati dell'Object Pascal, che hanno un ruolo nel linguaggio. L'help di Delphi distingue tra parole riservate e direttive: le parole riservate non possono essere usate come identificatori, mentre le direttive potrebbero, in teoria, essere usate come identificatore anche se in pratica e' meglio non farlo.
Nella Tabella 2.1 si puo' vedere una lista completa di identificatori che hanno uno specifico ruolo in Object Pascal (in Delphi 4), incluse parole chiave e parole riservate.
Tabella 2.1: Keywords e altre parole riservate nel linguaggio Object Pascal:
Keyword | Ruolo |
---|---|
absolute | directive (variables) |
abstract | directive (method) |
and | operator (boolean) |
array | type |
as | operator (RTTI) |
asm | statement |
assembler | backward compatibility (asm) |
at | statement (exceptions) |
automated | access specifier (class) |
begin | block marker |
case | statement |
cdecl | function calling convention |
class | type |
const | declaration or directive (parameters) |
constructor | special method |
contains | operator (set) |
default | directive (property) |
destructor | special method |
dispid | dispinterface specifier |
dispinterface | type |
div | operator |
do | statement |
downto | statement (for) |
dynamic | directive (method) |
else | statement (if or case) |
end | block marker |
except | statement (exceptions) |
export | backward compatibility (class) |
exports | declaration |
external | directive (functions) |
far | backward compatibility (class) |
file | type |
finalization | unit structure |
finally | statement (exceptions) |
for | statement |
forward | function directive |
function | declaration |
goto | statement |
if | statement |
implementation | unit structure |
implements | directive (property) |
in | operator (set) - project strucure |
index | directive (dipinterface) |
inherited | statement |
initialization | unit structure |
inline | backward compatibility (see asm) |
interface | type |
is | operator (RTTI) |
label | declaration |
library | program structure |
message | directive (method) |
mod | operator (math) |
name | directive (function) |
near | backward compatibility (class) |
nil | value |
nodefault | directive (property) |
not | operator (boolean) |
object | backward compatibility (class) |
of | statement (case) |
on | statement (exceptions) |
or | operator (boolean) |
out | directive (parameters) |
overload | function directive |
override | function directive |
package | program structure (package) |
packed | directive (record) |
pascal | function calling convention |
private | access specifier (class) |
procedure | declaration |
program | program structure |
property | declaration |
protected | access specifier (class) |
public | access specifier (class) |
published | access specifier (class) |
raise | statement (exceptions) |
read | property specifier |
readonly | dispatch interface specifier |
record | type |
register | function calling convention |
reintroduce | function directive |
repeat | statement |
requires | program structure (package) |
resident | directive (functions) |
resourcestring | type |
safecall | function calling convention |
set | type |
shl | operator (math) |
shr | operator (math) |
stdcall | function calling convention |
stored | directive (property) |
string | type |
then | statement (if) |
threadvar | declaration |
to | statement (for) |
try | statement (exceptions) |
type | declaration |
unit | unit structure |
until | statement |
uses | unit structure |
var | declaration |
virtual | directive (method) |
while | statement |
with | statement |
write | property specifier |
writeonly | dispatch interface specifier |
xor | operator (boolean) |
Queste non sono regole generali per costruire espressioni, visto che principalmente dipendono dagli operatori sui set, piu' diversi altri. Le espressioni possono essere usate per determinare il valore da assegnare ad una variabile, per calcolare il parametro di una funzione o procedura, o per testare una condizione. Le espressioni possono anche includere chiamate a funzioni. Ogni volta che si esegue un'operazione sul valore di un identificatore, invece di usare l'identificatore stesso, questa e' un'espressione.
Le espressioni sono comuni a quasi tutti i linguaggi di programmazione. Un'espressione e' una qualsiasi combinazione valida di costanti, variabili, valori letterali e risultati di funzione. Le espressioni possono anche essere passate ai parametri valore di una procedura o funzione, ma mai ad un parametro passato per riferimento (il quale richiede un valore al quale assegnarlo).
Se si e' scritto almeno un programma, si sa che cosa e' un'espressione. Qui mettero' in evidenza elementi specifici degli operatori Pascal. Si puo' vedere una lista di operatori raggruppati per precedenza (Tabella 2.1).
Nota: Contrariamente a diversi altri linguaggi di programmazione, gli operatori and e or hanno la precedenza sugli operatori relazionali. Cosi' se si scrive a < b and c < d, il compilatore valutera' per prima l'operazione and, generando quindi un errore. Per questa ragione bisogna racchiudere ogni espressione < in parentesi: (a < b) and (c < d).
Diversi operatori hanno diversi significati a seconda dei tipi di dato. Per esempio l'operatore + puo' essere usato per sommare due numeri, concatenare due stringhe, unire due insiemi e anche aggiungere un offset ad un puntatore PChar. In Pascal pero', non si possono sommare due caratteri come in C.
Un altro strano operatore e' div. In Pascal, si puo' eseguire la divisione tra due numeri qualsiasi (reali o interi) con l'operatore /, invariabilmente si otterra' un risultato reale. Se bisogna dividere due interi ed ottenere un risultato di tipo integer, si deve usare l'operatore div.
Tabella 2.2: Operatori del linguaggio Pascal, raggruppati per Precedenza
Operatori Unari (Precedenza piu' alta) | |
---|---|
@ | Indirizzo di una variabile o funzione (ritorna un puntatore |
not | Not booleano o bitwise |
Operatori di moltiplicazione | |
* | Moltiplicazione aritmetica o intersezione di insiemi |
/ | Divisione floating-point |
div | Divisione intera |
mod | Modulo (il resto di una divisione intera) |
as | Typecast sicuro (RTTI) |
and | And booleano o bitwise |
shl | Left Shift bitwise |
shr | Right Shift bitwise |
Operatori di addizione | |
+ | Somma aritmetica, unione di insiemi, concatenazione di stringhe, somma di offset |
- | Sottrazione aritmetica, sottrazione di insiemi, sottrazione di offset |
or | Or booleano o bitwise or |
xor | Or esclusivo boolean o bitwise |
Operatori relazionali e comparativi (Precedenza piu' bassa) | |
= | Test di uguaglianza |
<> | Test di non uguaglianza |
< | Test minore di |
> | Test maggiore di |
<= | Test minore o uguale di, o sottoinsieme di un insieme |
>= | Test maggiore o uguale di, o sovrainsieme di un insieme |
in | Test di appartenenza ad un insieme |
is | Test di compatibilita' di tipo (operatore RTTI) |
Gli operatori sugli insiemi (set) includono l'unione (+), la differenza (-), l'intersezione (*), test sugli elementi contenuti (in) piu' diversi altri operatori relazionali. Per aggiungere un elemento ad un insieme, si puo' fare l'unione del set con un altro che contiene solo l'elemento che serve. Ecco un esempio in Delphi relativo ai font:
Style := Style + [fsBold]; Style := Style + [fsBold, fsItalic] - [fsUnderline];
Come alternativa, si possono usare le procedure standard Include e Exclude, che sono molto piu' efficienti (ma non possono essere usate con le proprieta' di tipo set dei componenti, siccome richiedono un parametro l-value):
Include (Style, fsBold);
Adesso che si conosce lo schema di base di un programma Pascal, si e' pronti per comprenderne i dettagli. Partiremo con l'esplorazione delle definizioni di tipi di dato predefiniti e creati dall'utente, continuando con l'uso delle keyword per formare istruzioni nei programmi.
© Copyright Marco Cantù, Wintech Italia Srl 1995-2000