En quoi la gestion des sauts de ligne par Python diffère-t-elle des points-virgules automatiques de JavaScript?

41

Javascript a une fonctionnalité appelée Insertion automatique des points-virgules. En gros, si l'analyseur rencontre un jeton non valide et que le dernier jeton précédent était un saut de ligne, il insère un point-virgule à l'emplacement du saut de ligne. Cela vous permet en principe d'écrire tout votre code javascript sans point-virgule, mais vous devez connaître certains cas extrêmes, surtout si vous avez un mot clé de retour puis la valeur que vous souhaitez renvoyer sur une nouvelle ligne.

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

À cause de ces pièges, des dizaines d'articles portant des titres tels que "L'insertion automatique des points-virgules est diabolique", "Toujours utiliser les points-virgules en Javascript", etc.

Mais en Python, personne n’utilise jamais les points-virgules et il a exactement les mêmes pièges.

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

Fonctionne exactement de la même manière, et pourtant personne n’a une peur mortelle du comportement de Pythons.

Je pense que les cas où le javascript se comporte mal sont assez rares pour pouvoir les éviter facilement. Renvoyer + valeur sur une nouvelle ligne? Les gens font-ils vraiment beaucoup?

Des opinions? Utilisez-vous des points-virgules en javascript et pourquoi?

Einar Egilsson
la source
3
Cela ne fonctionne pas exactement de la même manière. L'insertion de point-virgule ne va pas où la nouvelle ligne est nécessairement en JavaScript. Voir le deuxième exemple sur cette page Wikipedia . Le point-virgule n'est pas inséré à l'emplacement de la nouvelle ligne dans cet exemple.
Reid
1
Mon argument n'était pas que le fait d'utiliser des points-virgules et de ne pas les utiliser fonctionne exactement de la même manière, mais plutôt que les cas extrêmes en javascript et en python étaient les mêmes. Il existe certainement quelques cas extrêmes où vous devez savoir ce qui se passe. Meilleur article que j'ai lu sur le sujet: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson
4
Je mets des points-virgules en JavaScript pour la même raison que j'utilise des points dans les phrases. Bien sûr, l’interprète peut généralement donner un sens à vos déclarations sans elles, mais sa forme est simplement mauvaise.
JD Isaacks
3
Vous pourriez envisager d'écrire un code python valide dans vos exemples. L'indicateur de commentaire n'est #pas «//».
Aaron Dufour
2
"Explicite est toujours meilleur qu'implicite"

Réponses:

62

La raison en est qu’en Python, les nouvelles lignes constituent un moyen non équivoque de séparer les lignes de code; c'est par conception, et la façon dont cela fonctionne a été minutieusement réfléchie. En conséquence, le code python est parfaitement lisible et sans ambiguïté, sans aucun marqueur de fin d’instruction spécial (à l’exception de la nouvelle ligne).

En revanche, Javascript a été conçu avec une syntaxe de type C, les instructions se terminant toujours par un point-virgule. Pour rendre le langage plus tolérant aux erreurs, il essaie de deviner où le point-virgule supplémentaire doit aller pour corriger le code. Dans la mesure où cela a été adapté en quelque sorte à la syntaxe C, il ne fonctionne pas toujours comme prévu (parfois, l'interpréteur de script devine mal) et peut générer un code assez contre-intuitif.

Ou encore, argumenter en termes "explicite vaut mieux qu'implicite": en Python, une nouvelle ligne est déjà complètement explicite, alors qu'en Javascript, elle est ambiguë. Vous ajoutez donc le point-virgule pour le rendre explicite.

tdammers
la source
3
Oh, et vous pouvez mettre du code dans les commentaires en utilisant des citations arrières.
tdammers
1
Un bon exemple de cas où une insertion automatique de point-virgule finira par
produire des
5
En python, les règles sont assez simples: les instructions se terminent par des sauts de ligne sauf s’il existe une chaîne multiligne non fermée ("" "," '"), un dict non fermé ({}), une liste non fermée ([]) ou une barre oblique inverse immédiatement En javascript, les règles sont nettement plus compliquées
Aaron Dufour
5
Couvrir 99% des erreurs est un bon moyen de ne laisser que les plus difficiles à trouver. C'est bien de les laisser en python car il existe des règles simples qui couvrent 100% des problèmes.
Aaron Dufour
1
@Aaron: Vous avez oublié "un ensemble de parenthèses non fermé (())". (Pas strictement "un tuple non fermé" car les parenthèses ne sont pas utilisées que pour les n-uplets.)
JAB
28

Je pense que la façon dont cela fonctionne en Python présente une différence fondamentale. Citation de l'article Einar Egilsson: "un point-virgule n'est pas impliqué à la fin d'une ligne si le premier jeton de la ligne suivante peut être analysé dans le cadre de la même déclaration".

En Python, un saut de ligne termine toujours l'instruction, sauf dans certains cas assez évidents, comme dans une expression entre parenthèses. JavaScript, d’autre part, essaiera d’analyser autant de lignes que possible avant de terminer l’instruction, ce qui pourrait conduire à des choses comme celles-ci:

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

// Fooled you! We're actually invoking it.
(14)
Henrik
la source
8
Maintenant, voici une torsion amusante sur celui-ci. Remplacez 14 par quelque chose comme (a + 1) ? do_something() : do_something_else();et tout à coup, la zone est définie sur la valeur de retour de do_something()ou do_something_else()et vous êtes complètement confus.
Reid
20

Je minimise souvent mes fichiers JS en mode de production. Signifie, en supprimant les commentaires et les sauts de ligne.

Sans l'utilisation de points-virgules, cela briserait mon javascript.

Deradon
la source
8
OK, c'est valide. Mais si votre minimiseur est un analyseur syntaxique réel, il peut les insérer à nouveau si nécessaire. Ou tout simplement pas supprimer les sauts de ligne, => vous conservez les sauts de ligne, perdez les points-virgules, ils sont à peu près le même nombre, donc rien n'est perdu.
Einar Egilsson
2
@Einar Egilsson Closure Compiler le fait effectivement.
seriousdev
1
Toutes choses étant égales par ailleurs, une nouvelle ligne correspond au même nombre d'octets qu'un point-virgule. Votre minimiseur peut supprimer toutes les nouvelles lignes, mais nécessite ensuite la présence de points-virgules. C'est un échange égal.
Logan Bailey
3
@Logan: Cela suppose des sauts de ligne d'un octet ;-)
Cameron
1
Bien sûr, si nous utilisions Python à la place de Javascript, nous devions coder moins pour faire la même chose, donc le fait que les points-virgules utilisent quelques octets de moins que l'indentation est un point discutable.
BlueRaja - Danny Pflughoeft
5

Cela ne fonctionne pas comme vous le décrivez.

Javascript a une fonctionnalité appelée Insertion automatique des points-virgules. En gros, si l'analyseur rencontre un jeton non valide et que le dernier jeton précédent était un saut de ligne, il insère un point-virgule à l'emplacement du saut de ligne.

C'est faux. Exemple:

return
  1 + 2;

1est un jeton parfaitement valide, mais l'analyseur insérera toujours un point-virgule directement après return.

Comme vous le voyez, même vous ne pouvez pas dire exactement où se produira un point-virgule.

Le problème avec l'insertion automatique est double:

  • D'une part, les gens peuvent laisser un point-virgule où l'insertion automatique ne peut pas déterminer qu'il faut en insérer.
  • En outre, un point-virgule peut être inséré là où il n'est pas prévu, comme ci-dessus.

Bien entendu, l’utilisation de points-virgules après chaque instruction n’aide que pour la première source d’erreurs.

En tout cas, comme vous pouvez le deviner à présent, je pense que l’insertion automatique de points-virgules dans la syntaxe C-like est une mauvaise idée.

Svante
la source
1
La spécification ECMA Script spécifie explicitement les cas où un point-virgule sera inséré. La ligne "Vous ne pouvez pas dire exactement où se produira un point-virgule" est incorrecte. Le problème est que cela n'est pas intuitif dans certains cas, ce qui rend plus difficile d'enseigner à quelqu'un qui ne comprend pas comment cela fonctionne.
zzzzBov
1
@zzzzBov: Oui, il y a une spécification exacte, mais est-ce que quelqu'un a vraiment tous les cas en tête lors du codage? Êtes-vous sûr? Les programmeurs sont paresseux, et à juste titre; ils ne veulent pas avoir à se souvenir d'une règle compliquée alors qu'une règle beaucoup plus simple ferait l'affaire. Alors, ils essaient de se déplacer en ayant à se souvenir.
Svante
Je conviens que l’insertion de point-virgule est largement inutile. Je dis juste qu'il y a une différence entre dire "vous ne savez pas où vont les points-virgules" et "la spécification pour l'insertion de points-virgules est un fouillis
involontaire
1
@Svante: Mais l'exemple de retour nous montre que nous devons quand même connaître ces règles. Là vous avez utilisé un point-virgule mais cela ne vous a pas aidé à faire ce que vous vouliez. Donc, étant donné que le langage a cette fonctionnalité, nous avons l'option (1) d'écrire des points-virgules partout et de connaître les règles afin de comprendre ce qui va arriver (2) de ne pas écrire de points-virgules partout et de comprendre les règles afin de comprendre ce qui va se passer. Compte tenu de ce choix, je pense que je préférerais éviter les points
Einar Egilsson
4

Je dirais une raison simple:

Javascript ressemble à "un peu java-ish" ou "un peu C-ish". Bien sûr, c'est un langage dynamique, donc ça a l'air différent ... mais regardons les choses en face: il y a des accolades. Les langues avec des accolades ont généralement des points-virgules. Les réflexes naturels entrent en jeu et font passer votre doigt vers la touche point-virgule avant de frapper Enter.

Python, au contraire, même d’un simple coup d’œil, est totalement différent. Par conséquent, peu ou pas d'analogie avec "les langages ennuyeux standard" est formée intuitivement et lorsque l'on entre dans le "mode python", l'absence de point-virgule est tout à fait naturelle.

Kos
la source
2

Il y a un certain nombre de bonnes raisons de ne pas utiliser l'insertion de point-virgule en JavaScript.

Cela est principalement dû au fait que l'insertion de point-virgule, telle que définie dans le standard ECMAScript, n'est pas intuitive dans certains cas. @Svante signale un cas returnoù l'utilisation de la nouvelle ligne posera problème.

Ce qu'il ne mentionne pas, c'est que cela posera des problèmes si vous utilisez également des points-virgules, car l'insertion de points-virgules se produit que vous le vouliez ou non.

Une autre très bonne raison de ne pas utiliser l'insertion de point-virgule est le contrôle de sortie. Dans de nombreux cas, JavaScript est exécuté à l'aide d'un minifier avant d'être utilisé en production. Certains minifiers peuvent traiter les cas d'insertion automatique point-virgule, mais je ne vois aucune raison de compter sur elle fonctionne parfaitement

De plus, pour les systèmes de gestion de contenu, le code JavaScript en ligne peut être auto-minifié, et j'ai déjà vu plusieurs cas dans lesquels le minifieur automatique supprime simplement les commentaires et supprime les espaces (y compris les nouvelles lignes) à partir du début et de la fin de chaque ligne.

Pour les auteurs qui n'ont pas le choix des outils choisis, il est beaucoup plus facile de s'en tenir à un format qui fonctionne dans la grande majorité des cas.

zzzzBov
la source
Ah, désolé, mais en ce qui concerne votre troisième paragraphe, je le mentionne dans mon avant-dernière phrase. :)
Svante
Oui, le problème de l'outillage est valide (bien que de bons minificateurs devraient le gérer, par exemple le compilateur Closure). Mais à mon avis, nous devons quand même connaître ces règles, pour éviter des choses comme l’exemple du «retour». Et une fois que je connais les règles, je pourrais aussi bien utiliser la fonctionnalité, en particulier parce qu'elle rend le code (IMO) plus lisible.
Einar Egilsson
1

Ne pas utiliser de point-virgule est une recette d'échec lorsque vous réduisez vos fichiers en fichiers JavaScript. C'est pourquoi j'en ai peur.

Moine oriental
la source
1

En Javascript, vous pouvez écrire un programme qui serait syntaxiquement correct en l'absence d'insertion de point-virgule automatique. ASI transformera ce programme en un programme syntaxiquement correct différent (par exemple, transformer un code renvoyant une valeur en un code ne renvoyant rien). Il n'y a pas de cas analogue en Python. En Python toute nouvelle ligne qui peut mettre fin à une déclaration sera fin à une déclaration, à moins qu'il est échappé avec une barre oblique inverse. Techniquement, je suppose que les règles de Javascript sont également déterministes, mais je ne sais pas si vous pouvez résumer les règles de Javascript pour les déclarations finales en une seule phrase.

Ryan C. Thompson
la source
1

Dans la plupart des cas, l'ASI de JavaScript gère les choses comme prévu. Voici un exemple d'ASI qui ne se comporte peut-être pas comme prévu:

var i = 0

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

Ceci sera interprété comme appelant la fonction 0avec la fonction anonyme, puis exécutant le résultat. Dans ce cas, vous souhaitiez probablement effectuer une affectation, puis exécuter immédiatement la fonction anonyme.

Pour des personnes non familiarisées avec ASI, il peut être très déroutant de rencontrer de tels problèmes. Je recommande donc toujours aux développeurs de mon équipe d'utiliser des points-virgules.

(En passant: je n'utilise pas de points-virgules lorsque je travaille sur des projets personnels / secondaires, car je sais que personne d'autre n'aurait besoin de gérer le code.)

jay_soo
la source
1

Comme vous, je pense que c'est un peu paranoïaque. Les règles pour l'insertion de points-virgules sont bien définies en JavaScript, tout comme en Python et CoffeeScript. Personne ne lit Python ou CoffeeScript avec des points-virgules, alors pourquoi JavaScript est-il traité différemment?

Je pense que c'est une réaction excessive à la misère du code JavaScript typique d'il y a une dizaine d'années. JavaScript était perçu comme un langage faible, bogué, laid, pas bon. C'était gênant. Vous ne pourriez pas écrire un bon code en JavaScript!

Ensuite, les gens sont venus et ont essayé de prouver que vous pouviez écrire du code beau et clair en JavaScript. Le " règle toujours utiliser des points-virgules" faisait partie de cette vague. Et pour être honnête, certaines situations peuvent être un peu plus claires.

Pourquoi JavaScript est-il toujours traité différemment?

Il y a de l'inertie. Et il ne faut pas oublier que les personnes qui apprécient le code explicitement structuré préfèrent souvent les langages de type C. Les personnes qui apprécient le code implicitement structuré passent souvent à des langages de style non C (comme CoffeeScript).

Fermeture Cowboy
la source
0

Je les utilise en Javascript strictement pour la cohérence. Si la plupart des lignes ont

Python les a pour les cas extrêmes tels que les déclarations multiples sur une seule ligne, javascript les a et comme vous les trouverez régulièrement utilisés, je me conforme à la norme où ils sont utilisés.

Je ne trouve pas d'utilisation pour plusieurs déclarations sur la même ligne et je ne prévois donc pas l'utilisation de points-virgules.

Chris
la source
Oui, j'ai corrigé l'exemple Python. Mais le problème demeure, Python a aussi des points-virgules, vous pouvez les mettre après chaque déclaration (et le faire si vous en avez plus d'une sur chaque ligne), mais les gens ne les utilisent pas.
Einar Egilsson
0

Si vous utilisez quelque chose comme bundle-fu et le gestionnaire d'actifs pour votre application Web dans des rails, cela se briserait horriblement s'il ne rencontrait pas de point-virgule à la fin du jeton en javascript. C'est donc une bonne pratique d'en mettre un.

soumiset
la source
Eh bien, les trois grands, YUI Compressor, Closure Compiler et UglifyJS, font tous une insertion en point-virgule. Je ne suis pas surpris que le port ruby ​​de JSMin ait des problèmes.
Benjamin Atkin
0

Je ne me souviens plus de la version exacte d'IE, mais il y a des cas où IE va littéralement se tromper s'il manque un point-virgule. IIRC c'est quand vous avez dans le monde entier quelque chose comme:

var myFunc = function() {
  ...
}

Si vous n'ajoutez pas le; après l'accolade de fermeture, le programme échouera sur certaines versions d'IE. Cela, avec les autres raisons (y compris la recommandation de Crockford de toujours les utiliser explicitement), m'a amené à les utiliser explicitement dans tous les cas.

Apinstein
la source