Alcuni lo fanno, ma non quelli popolari per quanto ne so. C'è qualcosa di brutto nel annidare i commenti?
Ho intenzione di far annidare i commenti a blocchi nella (piccola) lingua su cui sto lavorando, ma vorrei sapere se questa è una cattiva idea.
Alcuni lo fanno, ma non quelli popolari per quanto ne so. C'è qualcosa di brutto nel annidare i commenti?
Ho intenzione di far annidare i commenti a blocchi nella (piccola) lingua su cui sto lavorando, ma vorrei sapere se questa è una cattiva idea.
Risposte:
Una cosa che nessuno ha ancora menzionato, quindi lo menzionerò: il desiderio di annidare i commenti spesso indica che il programmatore sta facendo qualcosa di sbagliato.
Innanzitutto, concordiamo sul fatto che l'unica volta che "annidamento" o "non annidamento" è visibile al programmatore è quando il programmatore scrive qualcosa di strutturalmente come questo:
do_something();
/* comment /* nested comment */ more comment */
do_something_else();
Ora, quando succede una cosa del genere in pratica? Certamente il programmatore non scriverà commenti nidificati che assomigliano letteralmente allo snippet sopra! No, in pratica quando annidiamo i commenti (o vorremmo poterli annidare), è perché vogliamo scrivere qualcosa del genere:
do_something(); /* do a thing */
/* [ajo] 2017-12-03 this turned out to be unnecessary
do_something_else(); /* do another thing */
*/
E questo è MALE. Questo non è uno schema che noi (come designer linguistici) vogliamo incoraggiare! Il modo corretto di scrivere lo snippet sopra è:
do_something(); /* do a thing */
Quel codice "sbagliato", quel falso inizio o qualunque cosa fosse, non appartiene alla base di codice. Appartiene, nella migliore delle ipotesi, alla storia del controllo del codice sorgente. Idealmente, non avresti mai nemmeno scritto il codice sbagliato, giusto? E se il codice sbagliato stava servendo uno scopo lì, avvertendo i manutentori di non ripristinarlo per qualche motivo, beh, probabilmente è un lavoro per un commento di codice ben scritto e intenzionale. Cercare di esprimere "non fare X" semplicemente lasciando un vecchio codice che fa X, ma commentato, non è il modo più leggibile o efficace per impedire alle persone di fare X.
Tutto questo si riduce a una semplice regola empirica che potresti aver sentito prima: non commentare il codice. (Ricerca di questa frase si accende un sacco di opinioni in accordo .)
Prima di chiedere: sì, linguaggi come C, C # e C ++ già danno il programmatore un'altra strumento per "commentate" grandi blocchi di codice: #if 0
. Ma questa è solo una particolare applicazione del preprocessore C, che è uno strumento ampio e utile a sé stante. In realtà sarebbe estremamente difficile e speciale per un linguaggio supportare la compilazione condizionale #if
e tuttavia non supportarla #if 0
.
Quindi, abbiamo stabilito che i commenti nidificati sono rilevanti solo quando il programmatore sta commentando il codice; e abbiamo stabilito (tramite il consenso di molti programmatori esperti) che commentare il codice è una cosa negativa.
Per completare il sillogismo, dobbiamo accettare che i progettisti linguistici hanno interesse a promuovere le cose buone e scoraggiare le cose cattive (supponendo che tutto il resto sia uguale).
Nel caso di commenti nidificati, tutto il resto è uguale: puoi tranquillamente ignorare le risposte a basso voto che sostengono che l'analisi del nidificato /*
sarebbe in qualche modo "difficile" per il parser. (I nidificati /*
non sono più difficili di quelli nidificati (
, che quasi tutti i parser al mondo devono già gestire.)
Quindi, a parità di tutto il resto, un progettista di lingue dovrebbe rendere facile annidare i commenti (ovvero commentare il codice) o difficile? Ricorda che commentare il codice è una cosa negativa.
QED
Nota. Nota che se non consenti commenti nidificati, allora
hello /* foo*/bar.txt */ world
è un "commento" fuorviante - equivale a
hello bar.txt */ world
(che è probabilmente un errore di sintassi). Ma se si fa permettono commenti nidificati, quindi
hello /* foo/*.txt */ world
è un "commento" fuorviante - equivale a
hello
ma lascia il commento aperto fino alla fine del file (che di nuovo è quasi certamente un errore di sintassi). Quindi nessuno dei due modi è particolarmente meno soggetto a errori di sintassi involontari. L'unica differenza sta nel modo in cui gestiscono l' antipasto intenzionale del codice commentato.
#if DEAD
è l'esempio canonico e meglio progettato. In molte lingue puoi semplicemente racchiudere il codice morto nell'equivalente di if (DEAD)
. E in molti IDE, puoi effettivamente rimuovere il codice morto e fare affidamento su Ctrl + Z e / o controllo versione per recuperarlo se lo desideri. Lasciare un commento, dotstring, qualunque cosa, il cui testo è un mucchio di codice morto, è ancora l' opzione peggiore per la leggibilità.
Poiché la maggior parte delle implementazioni utilizza lexing separate e fasi di analisi e per il lexing usano semplici espressioni regolari. I commenti vengono trattati come spazi bianchi, ovvero token ignorati, e quindi devono essere risolti interamente in un passaggio lexing. L'unico vantaggio di questo approccio è l'analisi della velocità. Numerosi svantaggi includono gravi limitazioni alla sintassi (ad esempio, la necessità di mantenere un insieme fisso di parole chiave indipendenti dal contesto).
È perfettamente possibile creare un lexer in grado di gestire i commenti nidificati. Quando consuma spazi bianchi, quando vede /*
può aumentare un contatore di profondità e diminuirlo quando vede */
, e fermarsi quando la profondità è zero. Detto questo, ho fatto molti parser e non ho mai trovato una buona ragione per annidare i commenti.
Se i commenti possono essere nidificati, allora un aspetto negativo è che è facile bilanciare i loro fini e, a meno che tu non abbia un editor sofisticato, può nascondere invisibilmente il codice che presumi sia lì.
Un lato positivo dei commenti che non nidificano è qualcosa del genere:
/*
some code
more code
blah blah blah
/**/
dove puoi facilmente commentare dentro o fuori il codice rimuovendo o aggiungendo la prima riga - una modifica di 1 riga. Naturalmente, se quel codice stesso contiene un commento, questo si spezzerebbe, a meno che tu non autorizzi anche //
commenti in stile C ++ . Quindi è quello che tendo a fare.
//
i commenti sono anche in stile C99.
/*$token
, dov'è identifier
qualsiasi token alfanumerico, e la fine del commento è token$*/
. Sarebbe relativamente semplice per il tokenizer includere il codice per verificare che ogni segno di commento finale contenga il token corretto per il blocco corrispondente di commento iniziale.
Poiché nessun altro lo ha menzionato, elencherò alcune lingue che supportano i commenti nidificati: Rexx, Modula-2, Modula-3, Oberon. Nonostante tutte le lamentele qui per problemi di velocità e difficoltà, nessuno di questi sembra avere problemi enormi.
Un buon punto per annidare i commenti di blocco è che puoi commentare facilmente grandi porzioni di codice (beh, quasi, a meno che tu non abbia la sequenza finale dei commenti di blocco in una costante di stringa).
Un metodo alternativo è anteporre un gruppo di righe con la sequenza di inizio dei commenti di riga se si dispone di un editor che lo supporta.
Haskell ha annidato i commenti in blocco, ma la maggior parte delle persone non sembra accorgersene o lamentarsene. Immagino che ciò sia dovuto al fatto che le persone che non si aspettano commenti nidificati tendono ad evitarli in quanto questo sarebbe un errore lessicale in altre lingue.
Il supporto dei commenti a blocchi nidificati complica il parser, che è sia più lavoro che potrebbe aumentare il tempo di compilazione. Immagino che non sia una funzionalità molto necessaria per una lingua, quindi è meglio usare il tempo e gli sforzi su altri miglioramenti e ottimizzazioni.
Secondo me la semplicità è sempre una buona cosa nel progettare qualcosa. Tieni presente che è più semplice aggiungere una funzionalità che rimuoverla. Una volta che permetti i commenti nidificati e ci sono programmi là fuori che lo utilizzano, non sarai in grado di eliminarli senza interrompere la compatibilità.
/*/**/
Una probabile ragione è che il parser deve gestire i commenti nidificati, poiché il sapore delle espressioni regolari comunemente utilizzate nei lexer non supporta la ricorsione. Quelli semplici possono essere eliminati come spazi bianchi dal lexer, quindi sono più semplici da implementare in quel modo.
Chissà? Immagino perché supportare i commenti nidificati è più lavoro - dovresti mantenere una pila di qualche tipo e perché complica la grammatica della lingua.
I commenti nidificati significano lavoro extra per il parser. Di solito quando vedi l'inizio di un commento, ignori tutto fino all'indicatore di commento finale. Per supportare i commenti nidificati è necessario analizzare anche il testo nei commenti. Il problema più grande, tuttavia, è che un programmatore deve fare attenzione a chiudere correttamente tutti i commenti nidificati o porterà a errori di compilazione. L'implementazione corretta di un compilatore è qualcosa che può essere fatto, ma tenere traccia dei commenti annidati come programmatore è piuttosto soggetto a errori e irritante.