IMO, sono inclusi in Java e C # principalmente perché esistevano già in C ++. La vera domanda, quindi, è perché è C ++ in quel modo. Secondo The Design and Evolution of C ++ (§16.3):
La try
parola chiave è completamente ridondante, così come le { }
parentesi, tranne nel caso in cui più istruzioni vengano effettivamente utilizzate in un blocco di prova o in un gestore. Ad esempio, sarebbe stato banale consentire:
int f()
{
return g() catch(xxii) { // not C++
error("G() goofed: xxii");
return 22;
};
}
Tuttavia, ho trovato così difficile spiegare che la ridondanza è stata introdotta per salvare il personale di supporto da utenti confusi.
Modifica: Per quanto riguarda il motivo per cui questo potrebbe essere fonte di confusione, penso che si debba solo guardare alle affermazioni errate nella risposta di @Tom Jeffery (e, soprattutto, il numero di voti positivi che ha ricevuto) per rendersi conto che ci sarebbe un problema. Per il parser, questo in realtà non è diverso dall'abbinare else
s con if
s - mancano le parentesi graffe per forzare altri raggruppamenti, tutte le catch
clausole corrisponderebbero al più recente throw
. Per quelle lingue sbagliate che lo includono, le finally
clausole farebbero lo stesso. Dal punto di vista del parser, questo non è abbastanza diverso dalla situazione attuale da notare - in particolare, allo stato attuale delle grammatiche, non c'è davvero nulla per raggruppare le catch
clausole - le parentesi raggruppano le dichiarazioni controllate dalcatch
clausole, non le stesse clausole di cattura.
Dal punto di vista della scrittura di un parser, la differenza è quasi troppo piccola per essere notata. Se iniziamo con qualcosa del genere:
simple_statement: /* won't try to cover all of this */
;
statement: compound_statement
| simple_statement
;
statements:
| statements statement
;
compound_statement: '{' statements '}'
catch_arg: '(' argument ')'
Quindi la differenza sarebbe tra:
try_clause: 'try' statement
e:
try_clause: 'try' compound_statement
Allo stesso modo, per le clausole di cattura:
catch_clause: 'catch' catch_arg statement
vs.
catch_clause: 'catch' catch_arg compound_statement
Tuttavia, la definizione di un blocco try / catch completo non dovrebbe assolutamente cambiare. In entrambi i casi sarebbe qualcosa del tipo:
catch_clauses:
| catch_clauses catch_clause
;
try_block: try_clause catch_clauses [finally_clause]
;
[Qui sto usando [whatever]
per indicare qualcosa di facoltativo, e sto tralasciando la sintassi per un finally_clause
dato che non penso che abbia alcun rapporto con la domanda.]
Anche se non provi a seguire tutta la definizione grammaticale simile a Yacc lì, il punto può essere riassunto abbastanza facilmente: l'ultima affermazione (a partire da try_block
) è quella in cui le catch
clausole vengono abbinate alle try
clausole - e rimane esattamente il lo stesso sia che le parentesi graffe siano necessarie o meno.
Per ribadire / Riassumendo: il gruppo di parentesi graffe insieme delle dichiarazioni controllate dai le catch
s, ma farlo senza gruppo il catch
loro s. Come tale, quelle parentesi graffe non hanno assolutamente alcun effetto nel decidere quale catch
va con quale try
. Per il parser / compilatore l'attività è ugualmente facile (o difficile) in entrambi i casi. Nonostante questo, @ risposta di Tom (e il numero di up-voti è ricevuto) fornisce ampia dimostrazione del fatto che tale cambiamento una avrebbe utenti quasi certamente Confuse.
for
le parti dovrebbe essere chiamato qualcosa di simileinitial
,condition
estep
poichéinitial
non è necessario definire una variabile estep
non è necessario un incremento.