Como a manipulação de quebras de linha do Python difere dos pontos-e-vírgulas automáticos do JavaScript?

41

O Javascript possui um recurso chamado Inserção automática de ponto e vírgula, na qual, basicamente, se o analisador encontrar um token inválido e o último token anterior a uma quebra de linha, o analisador inserirá um ponto e vírgula no local da quebra de linha. Isso permite que você escreva basicamente todo o seu código javascript sem ponto-e-vírgula, mas você deve estar ciente de alguns casos extremos, principalmente se você tiver uma palavra-chave de retorno e o valor que deseja retornar em uma nova linha.

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

Devido a essas dicas, existem dezenas de artigos com títulos como 'A inserção automática de ponto e vírgula é má', 'Sempre use ponto e vírgula em Javascript' etc.

Mas, em Python, ninguém usa ponto e vírgula e ele tem exatamente as mesmas dicas.

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

Funciona exatamente da mesma maneira e, no entanto, ninguém tem muito medo do comportamento de Pythons.

Eu acho que os casos em que o javascript se comporta mal são poucos o suficiente para que você possa evitá-los facilmente. Retornar + valor em uma nova linha? As pessoas realmente fazem muito isso?

Alguma opinião? Você usa ponto e vírgula em javascript e por quê?

Einar Egilsson
fonte
3
Não funciona exatamente da mesma maneira. A inserção de ponto e vírgula não vai para onde a nova linha estiver, necessariamente, em JavaScript. Veja o segundo exemplo nesta página da Wikipedia . O ponto e vírgula não é inserido onde a nova linha está nesse exemplo.
Reid
1
Meu argumento não era que usar ponto-e-vírgula e não usá-los funcionava exatamente da mesma maneira, o ponto era que os casos de borda em javascript e python eram os mesmos. Certamente, existem alguns casos extremos em que você precisa saber o que está acontecendo. Melhor artigo que li sobre o assunto: inimino.org/~inimino/blog/javascript_semicolons
Einar Egilsson
4
Coloquei ponto e vírgula em JavaScript pelo mesmo motivo que uso períodos em frases. Certamente, o intérprete pode entender suas declarações sem elas, mas é apenas uma forma ruim.
JD Isaacks
3
Você pode considerar escrever python válido em seus exemplos. O indicador de comentário é #, não `// '.
Aaron Dufour
2
"explícito é sempre melhor do que implícito"

Respostas:

62

O motivo é que, no Python, as novas linhas são uma maneira inequívoca de separar as linhas de código; isso ocorre por design e a maneira como isso funciona foi bem pensada. Como resultado, o código python é perfeitamente legível e inequívoco sem marcadores especiais de final de instrução (além da nova linha).

Javascript, por outro lado, foi projetado com uma sintaxe semelhante a C, em que as instruções são sempre terminadas com ponto e vírgula. Para tornar o idioma mais tolerante a erros, ele tenta adivinhar onde os pontos e vírgulas extras devem ir para corrigir o código. Como isso foi adaptado retroativamente à sintaxe do tipo C, nem sempre funciona como esperado (às vezes, o intérprete de script acha errado) e pode gerar um código contra-intuitivo. \

Ou, argumentar em termos de "explícito é melhor do que implícito": no Python, uma nova linha já é completamente explícita, enquanto no Javascript é ambígua, portanto, adicione o ponto e vírgula para torná-lo explícito.

tdammers
fonte
3
Ah, e você pode colocar código nos comentários usando aspas.
tdammers
1
Um bom exemplo de um caso em que a inserção automática e vírgula vai acabar fazendo coisas inesperadas é esta: pastebin.com/aVeWGdya
HoLyVieR
5
Em python, as regras são bastante simples: as instruções terminam em quebras de linha, a menos que exista uma sequência multilinha não fechada ("" ", '' '), um ditado não fechado ({}), uma lista não fechada ([]) ou uma barra invertida imediatamente . antes da quebra de linha em JavaScript, as regras são significativamente mais complicado.
Aaron Dufour
5
Cobrir 99% dos erros é uma boa maneira de deixar para trás apenas os realmente difíceis de encontrar. Não há problema em deixá-los para trás em python, porque existem regras fáceis que cobrem 100% dos problemas.
Aaron Dufour
1
@ Aaron: Você esqueceu "um conjunto não incluído de parênteses (())". (Não estritamente "uma tupla não fechada" porque parênteses não são usados apenas para tuplas.)
JAB
28

Há uma diferença fundamental da maneira como funciona em Python, eu acho. Citando o post Einar Egilsson vinculado a: "um ponto-e-vírgula não está implícito no final de uma linha se o primeiro token da linha subseqüente puder ser analisado como parte da mesma declaração".

No Python, uma quebra de linha sempre termina a instrução, exceto em certos casos bastante óbvios, como dentro de uma expressão entre parênteses. O JavaScript, por outro lado, tentará analisar o máximo de linhas possível antes de terminar a instrução, levando potencialmente a coisas como esta:

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

// Fooled you! We're actually invoking it.
(14)
Henrik
fonte
8
Agora, aqui está uma reviravolta divertida neste. Substitua 14 por algo como (a + 1) ? do_something() : do_something_else();e, de repente, a área é definida como o valor de retorno de do_something()ou do_something_else()e você fica muito confuso.
Reid
20

Costumo minimizar meus arquivos JS no modo de produção. Significa remover comentários e quebras de linha.

Sem o uso de ponto e vírgula, isso quebraria meu Javascript.

Deradon
fonte
8
OK, isso é válido. Mas se o seu minimizador for um analisador real, poderá inseri-los novamente conforme necessário. Ou simplesmente não remova as quebras de linha, => você mantém as quebras de linha, perde os pontos e vírgulas, eles são aproximadamente o mesmo número, para que não haja nada perdido.
Einar Egilsson
2
O @Einar Egilsson Closure Compiler realmente faz isso.
seriousdev
1
Sendo tudo igual, uma nova linha é o mesmo número de bytes que um ponto e vírgula. Seu minimizador pode remover todas as novas linhas, mas exige que haja ponto e vírgula. É uma troca equilibrada.
Logan Bailey
3
@Logan: Isso supondo uma nova linha de bytes, é claro ;-)
Cameron
1
Obviamente, se usássemos Python em vez de Javascript, teríamos que codificar WAY menos para fazer a mesma coisa, portanto o fato de ponto-e-vírgula usar alguns bytes a menos que o recuo é um ponto discutível.
BlueRaja - Danny Pflughoeft
5

Não funciona como você descreve.

O Javascript possui um recurso chamado Inserção automática de ponto e vírgula, na qual, basicamente, se o analisador encontrar um token inválido e o último token anterior a uma quebra de linha, o analisador inserirá um ponto e vírgula no local da quebra de linha.

Isto está errado. Exemplo:

return
  1 + 2;

1é um token perfeitamente válido, mas o analisador ainda inserirá um ponto-e-vírgula logo após return.

Como você vê, nem você pode dizer exatamente onde um ponto e vírgula acontecerá.

O problema com a inserção automática é duplo:

  • Por um lado, as pessoas podem deixar um ponto e vírgula em que a inserção automática não pode determinar se é necessário inserir.
  • Além disso, um ponto e vírgula pode ser inserido onde não se destina, como acima.

Obviamente, o uso de ponto e vírgula após cada instrução ajuda apenas na primeira fonte de erros.

De qualquer forma, como você já deve adivinhar, acredito que a inserção automática de ponto e vírgula na sintaxe do tipo C é uma má idéia.

Svante
fonte
1
A especificação de script ECMA especifica explicitamente em quais casos um ponto-e-vírgula será inserido; portanto, sua linha "Você não sabe exatamente onde um ponto-e-vírgula acontecerá" está incorreta. A questão é que, em alguns casos, isso não é intuitivo, tornando mais difícil ensinar alguém que não entende como isso funciona.
precisa saber é o seguinte
1
@zzzzBov: Sim, existe uma especificação exata, mas alguém realmente tem todos os casos em mente ao codificar? Você tem certeza? Os programadores são preguiçosos, e com razão; eles não querem ter que lembrar de uma regra complicada quando uma muito mais simples seria. Então eles tentam se locomover tendo que se lembrar disso.
Svante
Concordo que a inserção de ponto e vírgula é em grande parte desnecessária. Eu só estou dizendo que há uma diferença entre dizer "você não tem idéia de onde ponto e vírgula vão" e "a especificação para a inserção ponto e vírgula é um amontoado intuitiva"
zzzzBov
1
@Svante: Mas o exemplo de retorno mostra que precisamos conhecer essas regras de qualquer maneira. Lá você usou um ponto-e-vírgula, mas não o ajudou a fazer o que queria. Portanto, como o idioma possui esse recurso, temos a opção de (1) Escrever ponto e vírgula em todos os lugares e conhecer as regras para entender o que acontecerá (2) Não escrever ponto e vírgula em qualquer lugar e entender as regras para entender o que acontecerá. Dado que escolha eu acho que eu prefiro ignorar as vírgulas
Einar Egilsson
4

Eu indicaria uma razão simples:

Javascript parece "meio java-ish" ou "meio C-ish". Claro que é uma linguagem dinâmica, por isso parece diferente ... mas convenhamos - existem aparelhos. Idiomas com chaves geralmente têm ponto e vírgula. Os reflexos naturais entram em ação e fazem seu dedo ir em direção à tecla de ponto e vírgula antes de pressionar Enter.

Python, pelo contrário, mesmo de relance parece totalmente diferente. Portanto, pouca ou nenhuma analogia com "as linguagens chatas padrão" é formada intuitivamente e, quando se entra no "modo python", a falta de ponto e vírgula é natural.

Kos
fonte
2

Existem várias boas razões para não usar a inserção de ponto e vírgula no JavaScript.

Principalmente porque a inserção de ponto-e-vírgula, conforme definida no padrão ECMAScript, não é intuitiva em alguns casos. O @Svante indica um caso em returnque o uso da nova linha causará problemas.

O que ele não menciona é que isso causará problemas se você estiver usando ponto e vírgula também, porque a inserção de ponto e vírgula acontece se você deseja ou não.

Outra boa razão para não usar a inserção de ponto e vírgula é o controle de saída. Em muitos casos, o JavaScript é executado através de um minificador antes de ser usado na produção. Alguns minificadores podem lidar com casos de inserção automática de ponto-e-vírgula, mas não vejo razão para confiar nele funcionando perfeitamente

Além disso, para sistemas de gerenciamento de conteúdo, o JavaScript embutido pode ser auto-minificado, e já vi vários casos em que o auto-removedor simplesmente remove comentários e apara os espaços em branco (incluindo novas linhas) do início e do fim de cada linha.

Para autores que não têm escolha de quais ferramentas estão sendo escolhidas, é muito mais fácil manter um formato que funcione na grande maioria dos casos.

zzzzBov
fonte
Ah, desculpe, mas a respeito de seu terceiro parágrafo, que faz menção de que na minha segunda a última frase. :)
Svante
Sim, o problema das ferramentas é válido (embora bons minimizadores devam lidar com isso, por exemplo, compilador de fechamento). Mas, na minha opinião, precisamos conhecer essas regras de qualquer maneira, para evitar coisas como o exemplo 'return'. E uma vez que conheço as regras, posso usar o recurso, especialmente porque ele torna o código (IMO) mais legível.
Einar Egilsson
1

Não usar ponto-e-vírgula é uma receita para a falha ao reduzir os arquivos JavaScript. É por isso que tenho medo disso.

Monge Oriental
fonte
1

Em Javascript, você pode escrever um programa que estivesse sintaticamente correto na ausência de inserção automática de ponto e vírgula, e o ASI transformará esse programa em um programa sintaticamente correto diferente (por exemplo, transformar código que retorna um valor em código que não retorna nada). Não há caso análogo no Python. Em Python qualquer nova linha que pode acabar com uma declaração irá acabar com uma declaração, a menos que seja escapou com uma barra invertida. Tecnicamente, suponho que as regras do Javascript sejam igualmente determinísticas, mas não sei se você poderia resumir as regras do Javascript para finalizar instruções em uma única frase.

Ryan C. Thompson
fonte
1

Na maioria dos casos, o ASI do JavaScript lida com as coisas conforme o esperado. Um exemplo de ASI talvez não se comporte da maneira que você esperaria é o seguinte:

var i = 0

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

Isso será interpretado como chamar a função 0com a função anônima e depois executar o resultado. Nesse caso, você provavelmente queria fazer uma atribuição e, em seguida, execute imediatamente a função anônima.

Para alguém não familiarizado com o ASI, pode ser muito confuso quando você se deparar com problemas como esse, por isso sempre recomendo que os desenvolvedores da minha equipe usem ponto e vírgula.

(Como um aparte: não uso ponto-e-vírgula ao trabalhar em projetos pessoais / paralelos, porque sei que ninguém mais precisaria manter o código.)

jay_soo
fonte
1

Como você, acho que é um pouco paranóico. As regras para inserção de ponto e vírgula estão bem definidas em JavaScript, assim como em Python e CoffeeScript. Ninguém nula Python ou CoffeeScript com ponto e vírgula, então por que o JavaScript é tratado de maneira diferente?

Eu acho que é uma reação exagerada ao estado miserável do código JavaScript típico de cerca de dez anos atrás - o JavaScript foi visto como uma linguagem fraca, com erros, feia e inútil. Foi uma vergonha. Você não poderia escrever um bom código em JavaScript!

Então, as pessoas apareceram e tentaram provar que era possível escrever um código bonito e claro em JavaScript. A regra " sempre use ponto e vírgula" fazia parte dessa onda. E para ser sincero, isso pode tornar algumas situações um pouco mais claras.

Por que o JavaScript ainda é tratado de maneira diferente?

Há inércia. E não se deve esquecer que as pessoas que apreciam códigos estruturados explicitamente preferem linguagens no estilo C. As pessoas que apreciam códigos estruturados implicitamente geralmente passam para linguagens que não são do tipo C (como o CoffeeScript).

Cowboy de encerramento
fonte
0

Eu os uso em Javascript estritamente para consistência. Se a maioria das linhas tiver

O Python os possui para casos extremos, como várias instruções em uma única linha, o javascript os possui e, como você os encontrará regularmente usados, estou em conformidade com a norma em que eles são usados.

Não consigo encontrar um uso para várias instruções na mesma linha e, portanto, não prevejo usar ponto e vírgula.

Chris
fonte
Sim, eu corrigi o exemplo do Python. Mas o ponto permanece: o Python também possui ponto-e-vírgula; você pode colocá-los após cada declaração (e deve ter se tiver mais de um em cada linha), mas as pessoas não os usam.
Einar Egilsson
0

Se você usar algo como bundle-fu e gerenciador de ativos para seu aplicativo da web nos trilhos, ele seria horrível se não encontrasse um ponto e vírgula no final do token em javascript. Portanto, é uma boa prática colocar um.

sutil
fonte
Bem, os três grandes, YUI Compressor, Closure Compiler e UglifyJS, fazem inserção de ponto e vírgula. Não estou surpreso que a porta ruby ​​do JSMin tenha problemas.
Benjamin Atkin
0

Não me lembro qual versão exata do IE, mas há alguns casos em que o IE literalmente errará se um ponto-e-vírgula estiver faltando. IIRC é quando você tem no escopo global algo como:

var myFunc = function() {
  ...
}

Se você não adicionar o; após a chave de fechamento, o programa realmente falhará em algumas versões do IE. Isso, juntamente com os outros motivos (incluindo a recomendação de Crockford de sempre usá-los explicitamente) me levou a sempre usá-los explicitamente em todos os casos.

apinstein
fonte