In che modo la gestione delle interruzioni di riga da parte di Python differisce dai punti e virgola automatici di JavaScript?


41

Javascript ha una funzione chiamata Inserimento punto e virgola automatico in cui fondamentalmente se il parser incontra un token non valido e l'ultimo token prima che fosse un'interruzione di riga, il parser inserirà un punto e virgola dove si trova l'interruzione di riga. Ciò ti consente di scrivere praticamente tutto il tuo codice javascript senza punti e virgola, ma devi essere consapevole di alcuni casi limite, soprattutto se hai una parola chiave return e quindi il valore che vuoi restituire su una nuova riga.

function test(){
    // This will return 'undefined', because return is a valid statement
    // and  "john" is a valid statement on its own.
    return 
          "john"
}

A causa di questi gotcha ci sono dozzine di articoli con titoli come "L'inserimento automatico del punto e virgola è il male", "Usa sempre il punto e virgola in Javascript" ecc.

Ma in Python nessuno usa mai il punto e virgola e ha esattamente gli stessi gotcha.

def test():
    # This will return 'undefined', because return is a valid statement
    # and  "john" is a valid statement on its own.
    return 
    "john"

Funziona esattamente allo stesso modo, eppure nessuno ha una paura mortale del comportamento di Pythons.

Penso che i casi in cui il javascript si comporta male siano pochi abbastanza da poterli evitare facilmente. Restituisce + valore su una nuova riga? Le persone lo fanno davvero molto?

Qualche opinione? Usi i punti e virgola in JavaScript e perché?


3
Non funziona esattamente allo stesso modo. L'inserimento del punto e virgola non va ovunque la newline sia, necessariamente, in JavaScript. Vedi il secondo esempio in questa pagina di Wikipedia . Il punto e virgola non viene inserito dove si trova la nuova riga nell'esempio.
Reid,

1
Il mio punto non era che usare i punti e virgola e non usarli funzionasse esattamente allo stesso modo, il punto era che i casi limite in javascript e python erano gli stessi. Ci sono certamente alcuni casi limite in cui devi sapere cosa sta succedendo. Miglior articolo che ho letto sull'argomento: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson

4
Ho messo i punti e virgola in JavaScript per lo stesso motivo per cui utilizzo i punti nelle frasi. Di certo l'interprete di solito può dare un senso alle tue affermazioni senza di esse, ma è solo una cattiva forma.
JD Isaacks,

3
Potresti considerare di scrivere un pitone valido nei tuoi esempi. L'indicatore di commento è #, non `// '.
Aaron Dufour,

2
"esplicito è sempre meglio che implicito"

Risposte:


62

Il motivo è che in Python le newline sono un modo inequivocabile di separare le righe di codice; questo è di progettazione e il modo in cui funziona è stato accuratamente studiato. Di conseguenza, il codice Python è perfettamente leggibile e inequivocabile senza speciali marcatori di fine istruzione (a parte la nuova riga).

Javascript, d'altra parte, è stato progettato tenendo presente una sintassi simile al C, in cui le istruzioni sono sempre terminate con un punto e virgola. Per rendere la lingua più tollerante agli errori, prova a indovinare dove dovrebbero essere aggiunti i punti e virgola per rendere il codice corretto. Dato che si trattava di una sorta di adattamento retroattivo alla sintassi simil-C, non sempre funziona come previsto (a volte, l'interprete di script indovina in modo errato) e può rendere il codice abbastanza contro-intuitivo. \

Oppure, argomentare in termini di "esplicito è meglio che implicito": in Python, una nuova riga è già completamente esplicita, mentre in Javascript è ambigua, quindi aggiungi il punto e virgola per renderlo esplicito.


3
Oh, e puoi inserire il codice nei commenti usando i backquotes.
martedì

1
Un buon esempio di un caso in cui l'inserimento automatico dei punti e virgola finirà per fare cose inaspettate è questo: pastebin.com/aVeWGdya
HoLyVieR

5
In Python, le regole sono abbastanza semplici: le istruzioni finiscono alle interruzioni di riga a meno che non vi sia una stringa multilinea non chiusa ("" ", '' '), un dict non chiuso ({}), un elenco non chiuso ([]) o una barra rovesciata immediatamente prima dell'interruzione di riga. In javascript, le regole sono significativamente più complicate
Aaron Dufour,

5
Coprire il 99% degli errori è un buon modo per lasciarsi alle spalle solo quelli davvero difficili da trovare. Va bene lasciarli indietro in Python perché ci sono regole facili che coprono il 100% dei problemi.
Aaron Dufour,

1
@Aaron: hai dimenticato "una serie chiusa di parentesi (())". (Non strettamente "una tupla non chiusa" perché le parentesi non sono usate solo per le tuple.)
JAB

28

C'è una differenza piuttosto fondamentale dal modo in cui funziona in Python, credo. Citando dal post Einar Egilsson collegato a: "un punto e virgola non è implicito alla fine di una riga se il primo token della riga successiva può essere analizzato come parte della stessa istruzione".

In Python un'interruzione di riga termina sempre l'istruzione, tranne in alcuni casi abbastanza ovvi come all'interno di un'espressione tra parentesi. JavaScript, d'altra parte, proverà ad analizzare quante più righe possibile prima di terminare l'affermazione, portando potenzialmente a cose come questa:

// Define a function and name it area.
area = function(r) {
    return r * r * 3.14159
}

// Fooled you! We're actually invoking it.
(14)

8
Ora ecco una svolta divertente su questo. Sostituisci 14 con qualcosa di simile (a + 1) ? do_something() : do_something_else();e all'improvviso, l'area è impostata sul valore di ritorno di do_something()o do_something_else()e rimani fortemente confuso.
Reid,

20

Spesso minimizzo i miei file JS in modalità di produzione. Mezzi, rimozione di commenti e interruzioni di riga.

Senza l'uso del punto e virgola, ciò spezzerebbe il mio Javascript.


8
OK, è valido Ma se il tuo minimizer è un vero parser potrebbe inserirli di nuovo se necessario. O semplicemente non rimuovere le interruzioni di riga, => si mantengono le interruzioni di riga, si perdono i punti e virgola, sono all'incirca lo stesso numero quindi non si perde nulla.
Einar Egilsson,

2
@Einar Egilsson Closure Compiler lo fa davvero.
seriousdev,

1
A parità di condizioni, una nuova riga ha lo stesso numero di byte di un punto e virgola. Il minimizer può eliminare tutte le nuove righe, ma richiede che siano presenti punti e virgola. È uno scambio uniforme.
Logan Bailey,

3
@Logan: questo presuppone una nuova riga di un byte, ovviamente ;-)
Cameron,

1
Ovviamente, se avessimo usato Python invece di Javascript, avremmo dovuto programmare meno MODO per fare la stessa cosa, quindi il fatto che i punti e virgola usino qualche byte in meno rispetto al rientro è un punto controverso.
BlueRaja - Danny Pflughoeft l'

5

Non funziona come descritto.

Javascript ha una funzione chiamata Inserimento punto e virgola automatico in cui fondamentalmente se il parser incontra un token non valido e l'ultimo token prima che fosse un'interruzione di riga, il parser inserirà un punto e virgola dove si trova l'interruzione di riga.

Questo è sbagliato. Esempio:

return
  1 + 2;

1è un token perfettamente valido, ma il parser inserirà comunque un punto e virgola subito dopo return.

Come vedi, nemmeno tu puoi dire esattamente dove accadrà un punto e virgola.

Il problema con l'inserimento automatico è duplice:

  • Per uno, le persone potrebbero lasciare un punto e virgola in cui l'inserimento automatico non può determinare che è necessario inserire.
  • Inoltre, un punto e virgola potrebbe essere inserito dove non è previsto, come sopra.

Naturalmente, l'uso del punto e virgola dopo ogni istruzione aiuta solo con la prima fonte di errori.

In ogni caso, come puoi immaginare, credo che l'inserimento automatico di punti e virgola nella sintassi di tipo C sia una cattiva idea.


1
La specifica dello script ECMA specifica esplicitamente quali casi verrà inserito un punto e virgola, quindi la riga "Non puoi dire esattamente dove accadrà un punto e virgola" non è corretta. Il problema è che in alcuni casi non è intuitivo, il che rende più difficile insegnare a qualcuno che non capisce come funziona.
zzzzBov,

1
@zzzzBov: Sì, esiste una specifica esatta, ma qualcuno ha davvero in mente tutti i casi durante la codifica? Sei sicuro? I programmatori sono pigri e giustamente; non vogliono ricordare una regola complicata quando ne farebbe una molto più semplice. Quindi cercano di aggirare doverlo ricordare.
Svante,

Concordo sul fatto che l'inserimento di punti e virgola è in gran parte superfluo. Sto solo dicendo che c'è una differenza tra dire "non hai idea di dove stanno andando i punti e virgola" e "le specifiche per l'inserimento dei punti e virgola sono un miscuglio non intuitivo"
zzzzBov

1
@Svante: Ma l'esempio di ritorno ci mostra che dobbiamo comunque conoscere queste regole. Lì hai usato un punto e virgola ma non ti ha aiutato a fare quello che volevi. Quindi, dato che la lingua ha questa caratteristica, abbiamo la possibilità di (1) scrivere punti e virgola ovunque e conoscere le regole in modo da capire cosa accadrà (2) Non scrivere punti e virgola ovunque e comprendere le regole in modo da capire cosa accadrà. Data questa scelta, penso che preferirei saltare i punti
Einar Egilsson il

4

Direi un semplice motivo:

Javascript sembra "kinda java-ish" o "kinda C-ish". Ovviamente è un linguaggio dinamico, quindi sembra diverso ... ma affrontalo: ci sono parentesi graffe. Le lingue con parentesi graffe generalmente hanno un punto e virgola. I riflessi naturali entrano in azione e fanno andare il dito verso il punto e virgola prima di colpire Enter.

Python, al contrario, anche a prima vista sembra totalmente diverso. Quindi, poca o nessuna analogia con "i linguaggi noiosi standard" è formata in modo intuitivo e quando si entra nella "modalità pitone", la mancanza di punti e virgola diventa naturale.


2

Esistono numerosi buoni motivi per non utilizzare l'inserimento di punti e virgola in JavaScript.

Principalmente perché l'inserimento di punti e virgola come definito nello standard ECMAScript non è intuitivo in alcuni casi. @Svante indica un caso in returncui l'utilizzo della nuova riga causerà problemi.

Ciò che non menziona è che causerà problemi anche se si utilizzano punti e virgola, poiché l'inserimento di punti e virgola avviene indipendentemente dal fatto che lo si desideri.

Un altro ottimo motivo per non utilizzare l'inserimento di punti e virgola è il controllo dell'output. In molti casi JavaScript viene eseguito attraverso un minificatore prima di essere utilizzato in produzione. Alcuni minificatori possono gestire casi di inserimento automatico di punti e virgola, ma non vedo alcun motivo per fare affidamento sul fatto che funzioni perfettamente

Inoltre, per i sistemi di gestione dei contenuti, JavaScript incorporato può essere minimizzato automaticamente e ho visto un numero di casi in cui il minificatore automatico rimuove semplicemente i commenti e taglia gli spazi bianchi (comprese le nuove righe) dall'inizio e dalla fine di ogni riga.

Per gli autori che non hanno la scelta di quali strumenti vengono scelti, è molto più semplice attenersi a un formato che funziona nella stragrande maggioranza dei casi.


Ah, scusa, ma per quanto riguarda il terzo comma, io faccio menzione che nel mio secondo-a-ultima frase. :)
Svante,

Sì, il problema degli utensili è valido (anche se i buoni minificatori dovrebbero gestirlo, ad esempio il compilatore di chiusura). Ma secondo me, dobbiamo comunque conoscere queste regole, per evitare cose come l'esempio del "ritorno". E una volta che conosco le regole, potrei anche usare la funzione, soprattutto perché rende il codice (IMO) più leggibile.
Einar Egilsson,

1

Non utilizzare il punto e virgola è una ricetta per l'errore quando si minimizzano i file JavaScript dei file. Ecco perché ne ho paura.


1

In Javascript, puoi scrivere un programma che sarebbe sintatticamente corretto in assenza dell'inserimento automatico di punti e virgola e ASI trasformerà quel programma in un altro programma sintatticamente corretto (ad esempio, trasformando il codice che restituisce un valore in codice che non restituisce nulla). Non esiste un caso analogo in Python. In Python ogni nuova riga che può terminare una dichiarazione si concluderà una dichiarazione, a meno che non sia cavata con una barra inversa. Tecnicamente, suppongo che le regole di Javascript siano ugualmente deterministiche, ma non so se si possano riassumere le regole di Javascript per terminare le dichiarazioni in una sola frase.


1

Nella maggior parte dei casi l'ASI di JavaScript gestisce le cose come previsto. Un esempio di ASI forse non si comporta come ti aspetteresti è questo:

var i = 0

(function() {
   // do something
})()

Questo verrà interpretato come chiamare la funzione 0con la funzione anonima, quindi eseguire il risultato. In questo caso probabilmente volevi fare un compito, quindi eseguire immediatamente la funzione anonima.

A qualcuno che non ha familiarità con l'ASI può essere molto confuso quando si verificano problemi come questo, quindi consiglio sempre agli sviluppatori del mio team di utilizzare i punti e virgola.

(A parte: non uso i punti e virgola quando lavoro su progetti personali / secondari perché so che nessun altro avrebbe bisogno di mantenere il codice.)


1

Come te, penso che sia un po 'paranoico. Le regole per l'inserimento del punto e virgola sono ben definite in JavaScript, proprio come in Python e CoffeeScript. Nessuno sporca Python o CoffeeScript con punti e virgola, quindi perché JavaScript viene trattato in modo diverso?

Penso che sia una reazione eccessiva allo stato miserabile del tipico codice JavaScript di circa dieci anni fa: JavaScript è stato visto come un linguaggio debole, difettoso, brutto, non buono. È stato un imbarazzo. Non è possibile scrivere un buon codice in JavaScript!

Poi, la gente è arrivato e ha cercato di dimostrare che si poteva scrivere bello, il codice libero in JavaScript. La regola "usa sempre punti e virgola" faceva parte di questa ondata. E ad essere onesti, può rendere alcune situazioni un po 'più chiare.

Perché JavaScript è ancora trattato in modo diverso?

C'è inerzia. E non bisogna trascurare il fatto che le persone che apprezzano il codice esplicitamente strutturato spesso preferiscono i linguaggi in stile C. Le persone che apprezzano il codice implicitamente strutturato spesso passano a linguaggi non di tipo C (come CoffeeScript).


0

Li uso in Javascript rigorosamente per coerenza. Se la maggior parte delle linee ha

Python li ha per casi limite come più istruzioni su una sola riga, javascript li ha e poiché li troverai regolarmente usati mi conformo alla norma in cui vengono utilizzati.

Non riesco a trovare un uso per più istruzioni sulla stessa riga e pertanto non prevedo l'utilizzo di punti e virgola.


Sì, ho corretto l'esempio di Python. Ma il punto rimane, Python ha anche i punti e virgola, sei il benvenuto a metterli dopo ogni istruzione (e devi farlo se ne hai più di uno su ogni riga) ma le persone non li usano.
Einar Egilsson,

0

Se usi qualcosa come bundle-fu e gestore delle risorse per la tua app Web su rotaie, si spezzerebbe in modo orribile se non incontrasse un punto e virgola alla fine del token in javascript. Quindi è una buona pratica metterne uno.


Bene, i tre grandi, YUI Compressor, Closure Compiler e UglifyJS, fanno tutti l'inserimento di punti e virgola. Non mi sorprende che il porto rubino di JSMin abbia problemi.
Benjamin Atkin,

0

Non ricordo quale versione esatta di IE, ma ci sono alcuni casi in cui IE sbaglierà letteralmente se manca un punto e virgola. IIRC è quando hai nell'ambito globale qualcosa come:

var myFunc = function() {
  ...
}

Se non aggiungi il; dopo la parentesi graffa di chiusura, il programma fallirà effettivamente su alcune versioni di IE. Che, insieme agli altri motivi (inclusa la raccomandazione di Crockford di usarli sempre esplicitamente), mi hanno portato a usarli sempre esplicitamente in ogni caso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.