Qual elemento de sintaxe você mais odeia em uma linguagem de programação usada com freqüência? [fechadas]


27

Não importa o quanto você goste de uma linguagem de programação, sempre há alguns detalhes que não são tão bons quanto poderiam ser.

Nesta pergunta, eu gostaria de focar especificamente nos elementos de sintaxe. Em uma linguagem de programação que você usa com freqüência (talvez a sua linguagem de programação favorita ou a que você é forçada a usar no trabalho), qual elemento de sintaxe você acha mais ilegível, obscuro, inconveniente ou desagradável?


@ Nathan Taylor, não para esta pergunta, mas para outra pergunta .
finnw

Esta pergunta foi modificada? Porque quando eu respondi, não estava focado em "elementos de sintaxe" ... Vou ter que modificar minha resposta agora.
Talvi Watia 20/09/10

@ Talvi: Não, tratava-se de sintaxe desde o início.
Timwi

@ Timwi estranho, deve ser um caso de 'responder a uma pergunta pensando que era diferente' então.
Talvi Watia

Se você pode votar e achar que essa é uma pergunta útil ou que possui respostas úteis abaixo, vote. Os sites StackExchange precisam de votos para criar uma boa comunidade. Você pode dar 30 votos por dia, não os desperdice. Especialmente usuários com alta reputação e baixa contagem de votos dados, por favor leia isto: meta.programmers.stackexchange.com/questions/393/…
Maniero

Respostas:


39

Inserção de ponto e vírgula em JavaScript.

Eu realmente não fui mordido por isso com frequência, mas é uma idéia tão fenomenalmente ruim que faz minha cabeça girar.


Aqui estão as regras (da seção 7.9 da ECMA-262)

  1. Quando o programa contém um token que não é permitido pela gramática formal, um ponto-e-vírgula é inserido se (a) houver uma quebra de linha nesse ponto ou (b) o token inesperado for uma chave de fechamento.
  2. Quando o final de um arquivo é atingido, se o programa não puder ser analisado de outra forma, um ponto-e-vírgula é inserido.
  3. Quando uma "produção restrita" é encontrada e contém um terminador de linha em um local onde a gramática contém a anotação "[sem LineTerminator aqui]" ", um ponto-e-vírgula é inserido.

Exemplo:

return 1; // returns 1

return
1; // returns undefined

2
JavaScript: O mundo o mais Misunderstood Linguagem de programação ~ Douglas Crockford
pramodc84

Sim, muitos esperam que o JavaScript seja uma "linguagem de forma livre", mas não é.
Andreas Rejbrand 13/09/10

13
Faz sentido quando você percebe que o JavaScript foi projetado para criar HTML, que também tem um longo histórico de tentativas de interpretar o que seu código "realmente significa" quando não é sintaticamente válido. (Veja-se a algum Robustez Princípio - o maior desastre na história da computação.)
Mason Wheeler

7
Esses tipos de erros, para mim, são um cheiro de código que o programador é desleixado e nunca trabalhou com as linguagens "estritas" formais que normalmente causariam um erro de sintaxe ao deixar o ponto e vírgula de fora.
Talvi Watia 20/09/10

7
Finalmente, alguém que também acha que o Princípio da Robustez é um desastre que fez do HTML a bagunça total.
Roman Starkov

39

Sintaxe de Java-bean devido à falta de propriedades de C #

/**
 * Name of user
 */
private String name;

/**
 * Gets name of user
 * @return Name of user
 */
public String getName() {
    return this.name;
}

/**
 * Sets name of user. 
 * @param name
 */
public void setName(final String name) {
    this.name = name;
}

GAH !!!

Problemas que tenho com isso

  • Demasiado código - Tenha um campo documentado, um método getter que esteja documentado e um método setter que esteja documentado. Este exemplo extremamente básico possui 20 linhas de código para uma única propriedade
  • Clutter método listas - "Deixe-me encontrar esse método, mão em: getX, getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ah lá está, hashCode.
  • Várias áreas de documentação levam a documentação ruim, desatualizada ou ausente - irritante ao tentar entender o que o código faz
  • Tão irritante que um terceiro tenha que criar um plugin para fazer isso facilmente - Spoon , Shark , entre outros.

9
Mais uma vez, quando o código é tão detalhado que precisa de ferramentas de geração automática, algo está errado. Eu sou do NetBeans, mas também tem a capacidade de gerar automaticamente getters e setters. Mas Javadoc cai fora do syn, ainda é detalhado, ainda Clutter javadoc, etc
TheLQ

11
Se você precisar de getters para tudo, algo está errado com o código do cliente .
finnw

7
Ter getters e setters quebra o encapsulamento. O campo também pode ser public. Os membros devem ser privados e devem ser manipulados com sensibilidade pela classe com lógica de nível superior, não com getters e setters do código do cliente.
greyfade

6
@greyfade: se for público, você não pode alterar facilmente o que o código de configuração faz (você precisará alterar todo o código que define o campo de fora).
Bart van Heukelom 18/09/10

3
@SHiNKiROU: Java parece limpo? Eu nunca ouvi isso antes! Minha principal reclamação com Java é o fato de que uma coisa aparentemente simples requer dezenas de linhas de código que eu preciso ignorar mentalmente.
configurador

33

Sensibilidade de espaço em branco.

Python me irrita a esse respeito. Quero dizer, eu recuo corretamente de qualquer maneira, mas me incomoda que eu precise . Tornar a apresentação parte da sintaxe me irrita.


8
você aprenderá a amá-lo
user10008

2
sintaxe é apresentação
Winston Ewert

32

A switchinstrução (em C, C ++, C #, Java etc.)

Aqui está um exemplo de por que considero altamente inconveniente:

switch (someVariable)
{
    case 1:
        int i = something();
        doSomething(i);
        break;

    case 2:
        int i = somethingElse();
        doSomethingElse(i);
        break;
}

Isso não é compilado porque a variável ié redeclarada no mesmo escopo. Parece um pequeno detalhe, mas me morde com muita frequência. Posso adicionar colchetes para atenuá-lo, mas seria bom se os colchetes fossem parte obrigatória da sintaxe e não houvesse um nível extra redundante de recuo. Eu também odeio ter que escrever o extra break. Isso seria muito melhor:

switch (someVariable)
case 1
{
    int i = something();
    doSomething(i);
}
case 2
{
    int i = somethingElse();
    doSomethingElse(i);
}
default
{
    ...
}

Isso faz com que pareça mais com uma cadeia if/ else, o que é uma coisa boa porque é semanticamente semelhante também. Pelo menos em C #, ainda assim não seria a mesma coisa, porque em uma switchdeclaração a ordem dos rótulos dos casos não importa, mas em um if/ elseisso importa.


1
Infelizmente, sua sintaxe aprimorada elimina o que é, sem dúvida, o maior recurso do switch na maioria desses idiomas: Fall-through. "Dispositivo de Duff" em C é um exemplo perfeito do valor desse "recurso incorreto" em particular. Também é comum em idiomas do tipo C usar fall-through em intérpretes e programas similares.
greyfade

7
Não, isso não acaba com isso. Requer apenas que seja mais explícito (usando um gotoou similar), como já é o caso em C #.
Timwi

8
@greyfade: Qualquer código que use o dispositivo de duff em C precisa sofrer uma morte horrível. Os compiladores tomam melhores decisões sobre esse tipo de coisa do que você.
Billy ONeal

4
@greyfade: Delphi fica em torno da questão de valor múltiplo, simplesmente permitindo que vários índices no caso: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Frank Shearar

3
@ jkerian: Agora imagine que breakera o padrão e apenas o avanço precisava ser especificado. Não há mais necessidade de lembrar de comentar! :)
Timwi

27

Declarações de matriz em VB.NET

Sempre esqueço que, ao inicializar matrizes fixas no VB.NET, você especifica o limite superior da matriz e não o número de elementos, como em C / C ++, PHP ou Java. Além do VB6 (não vamos lá ...), não consigo pensar em outra linguagem que faça dessa maneira:

Dim myArray(20) as Integer  '# Creates an array with 21 elements,
                            '# indexed from 0 to 20

Eu acho que todas as línguas BASIC fazem isso ... Eu sei que BASIC e QBasic originais.
Michael K

OMG que é realmente horrível .... +1 #
mikera

25

VB6 - Declaração e atribuição de variáveis ​​separadas

A maioria dos idiomas permite declarar uma variável e atribuí-la em uma linha de código; O VB6, por outro lado, força você a usar dois.

Dim i as Integer
i = 0

Dim derpderp as Collection
Set derpderp = new Collection

Você pode usar dois pontos para colocar dois comandos em uma linha, mas rapidamente fica confuso no código real.

Dim i as Integer: i = 0
Dim derpderp as Collection: Set derpderp = new Collection

7
+1 por ter que usar o VB6 como o idioma mais frequente.
Walter Walter

9
Eu uso diariamente..sob.
Systempuntoout

Pascal não tem uma sintaxe semelhante? Eu sempre pensei que era desagradável.
greyfade

1
Há um caso especial: se você Dim Hurp As New Collection, se acessar Hurpquando se referir Nothing, será magicamente inicializado antes do acesso. Se você o definir explicitamente Nothinge tocar novamente, ele será ressuscitado ... suspiro!
Jeffrey Hantin

1
+ 1 milhão para Derp. Derp de derp de tiddly tum de derp.
MVCylon #

24

Comentando em CSS

//não comenta linhas de código como em muitas outras línguas, como PHP e Javascript. Embora /* this is commented out */funcione, eu prefiro usar //.

É um incômodo, porque na metade do tempo eu esqueço que estou editando CSS e depois tenho que voltar e corrigir o erro.


Você pensaria hoje em dia que o CSS bruto seria considerado código de objeto.
Tom Hawtin - tackline

// funciona muito bem para comentar CSS. Eu faço isso o tempo todo. Tudo o que realmente estou fazendo é digitar lixo. mas parece funcionar pulando a linha imperceptível.
MVCylon

1
@MVCylon Se você usar // para comentar uma linha, qualquer coisa depois dessa linha também será ignorada. {dentro desse estilo específico} Em outras palavras, FALHA porque essas linhas não devem ser ignoradas.
Talvi Watia

20

PHP - ordenação consistente de argumentos

O PHP possui várias funções úteis para executar praticamente todas as operações que você pode imaginar em um array ou string. Muitas dessas operações requerem o uso de a $needlee a $haystack, mas funções diferentes as levam em ordens diferentes. Qual função requer quais argumentos é um daqueles fatos que meu cérebro se recusa a absorver, não importa quantas vezes eu os encontre!

Tome as funções in_array e strstr :

// Check whether $needle occurs in array $haystack
bool in_array (mixed $needle, array $haystack [, bool $strict])

// Check whether $needle is a substring of $haystack
string strstr (string $haystack, mixed $needle [, bool $before_needle=false])

Curiosamente, o PHP parece ser internamente consistente com essas ordenações, pois todas as funções de string parecem usar $haystack, $needleenquanto as funções de array são inversas, mas isso pode demorar um pouco para se acostumar com alguém novo no PHP. Há um bom post no ExpressionEngine falando sobre essa peculiaridade específica em mais detalhes, bem como uma discussão na lista de bugs do PHP , que apresenta uma resposta muito curta da equipe do PHP!

helly@php.net
Use um IDE decente então.

2
É mais fácil lembrar a ordem $needle, $haystackpois lembra a maneira de dizer encontrar uma agulha no palheiro .
Kievlaluno # 3/10

3
Protip: nas funções do array, a agulha vem primeiro. nas funções de string, o palheiro vem primeiro.
GSto 9/09/10

17
Eu amo o nome strstr. Tão lindamente sem sentido.
configurator

5
Basta ler a entrada vinculada no bugtracker do PHP. Sério, wtf? oO consistência do Imho é um problema válido para qualquer API e apenas responder com "use um IDE decente" não é uma resposta válida. Pelo menos, poderia ter sido menos inflamado pelos desenvolvedores.
Baelnorn 1/10/10

2
Honestamente, o que me deixa louco por isso é que não deveria ser uma função! Deve ser apenas um método: $ haystack-> find ($ needle). Negócio feito.
Riwalk 26/05

19

Python

self parâmetro nas definições de método da instância


Em um método de classe, geralmente é chamado de cls e o uso de self contraria as convenções.

Na verdade, faz sentido se você pensar sobre isso. É o mesmo que declarar um método privado em outras linguagens, o parâmetro self é apenas explícito em python, onde está implícito em outras linguagens. Se você deseja que esteja implícito, adicione o decorador @classmethod antes da declaração do método. Consulte docs.python.org/library/functions.html#classmethod . Aprender os detalhes de como isso funciona fornecerá algumas dicas sobre como isso é feito em outros idiomas implicitamente.
Evan Plaice

4
Eu entendo as razões e por que é deixado lá neopythonic.blogspot.com/2008/10/… mas ainda não gosto
Goran Peroš

@Evan Plaice: 'auto-parâmetro é apenas explícito em python, onde está implícito em outras línguas'. Isso é apenas uma parte da história. A outra parte é o python sendo digitado semanalmente. Juntos, é terrível, o esquecimento selfacontece com facilidade e custa tempo.
Maaartinus

@maaartinus Em seguida, adicione um decorador de método de classe aos métodos da instância. Não tem nada a ver com 'digitação fraca'. Isso apenas torna óbvia a relação entre métodos / funções estáticas (sem parâmetro 'self') e métodos de instância (inclui 'self'). Um método de instância não está ciente de sua classe pai, a menos que você faça uma referência a ele. Em outras línguas, a característica distintiva que descrevi está apenas oculta por trás do açúcar sintático. Se eu tivesse a opção de fazer tudo isso, começaria a aprender OOP em Python primeiro.
Evan Solha

18

Java

Período. Ponto final. Fim da história.

Onde começar? Ah, eu sei por onde começar: os genéricos incrivelmente complicados, feios, estúpidos e inerentemente quebrados de Java . Preciso dizer mais? :( Ok, tudo bem, então: digite apagamento .

Depois, há um gerenciamento não determinístico de recursos. Kewl footcher!

O que vem a seguir? Ah, sim: as expressões estúpidas de Java são a minha carne mais irritante e fervilhante. Não sei contar quantas vezes fui manejado por não ter barras invertidas suficientes. Isso é ainda pior do que não ter acesso a nenhuma propriedade Unicode deste milênio - o que é um touro completo. Dez anos de desatualização desatualizados !!! Completamente inútil. Jogue fora.

Depois, há o erro de que os atalhos da classe de caracteres não funcionam em não-ASCII. Que dor real! E nem pense em usar \p{javaWhiteSpace}; ele não faz a coisa certa com vários pontos de código de espaço em branco Unicode muito comuns.

Você sabia que há um \p{javaJavaIdentifierStart} propriedade? O que eles estavam pensando? Tão contentes por terem peepers tão espertos que se desentendem.

Já tentou usar o sinalizador CANON_EQ? Você sabe o que realmente faz e o que não faz? Que tal o chamado "caso Unicode"? Um monte de coisas normais da caixa simplesmente não funcionam.

Eles dificultam a criação de regexes de manutenção. O Java ainda não descobriu como escrever strings de múltiplas linhas, então você acaba escrevendo coisas insanas como esta:

    "(?= ^ [A-Z] [A-Za-z0-9\\-] + $)      \n"
  + "(?! ^ .*                             \n"
  + "    (?: ^     \\d+      $            \n"
  + "      | ^ [A-Z] - [A-Z] $            \n"
  + "      | Invitrogen                   \n"
  + "      | Clontech                     \n"
  + "      | L-L-X-X                      \n"
  + "      | Sarstedt                     \n"
  + "      | Roche                        \n"
  + "      | Beckman                      \n"
  + "      | Bayer                        \n"
  + "    )      # end alternatives        \n"
  + ")          # end negated lookahead   \n" 

Quais são todas essas novas linhas? Oh, apenas estupidez em Java. Eles usaram comentários Perl, não comentários Java ( idiotas! ), Que vão até o final da linha. Portanto, se você não colocar as que \nestão lá, corta o restante do seu padrão. Duh e double duh!

Não use expressões regulares em Java: você acabará querendo esmagar as coisas, tudo é tão doloroso e quebrado. Não acredito que as pessoas aguentam isso. Alguns não .

Então podemos começar a falar sobre o absurdo idiota de Java com codificações. Primeiro, há o fato de que a codificação da plataforma padrão é sempre uma codificação sem graça de 8 bits, mesmo que os charchars de Java sejam Unicode. Depois, há como eles não geram uma exceção em um erro de codificação. Você está garantido para receber porcaria. Ou que tal:

OutputStreamWriter(OutputStream out) 
          Creates an OutputStreamWriter that uses the default character encoding.
OutputStreamWriter(OutputStream out, Charset cs) 
          Creates an OutputStreamWriter that uses the given charset.
OutputStreamWriter(OutputStream out, CharsetEncoder enc) 
          Creates an OutputStreamWriter that uses the given charset encoder.
OutputStreamWriter(OutputStream out, String charsetName) 
          Creates an OutputStreamWriter that uses the named charset.

Qual é a diferença? Você sabia disso apenas um deles gerará uma exceção se você tiver um erro de codificação? O resto apenas açaima.

Depois, há a idiotice dos caracteres Java que não são suficientes para conter um caractere! Que diabos eles estão pensando? É por isso que eu os chamo de caracteres. Você precisa escrever um código como este se espera que funcione corretamente:

private static void say_physical(String s) { 
    System.out.print("U+");
    for (int i = 0; i < s.length(); i++) {
        System.out.printf("%X", s.codePointAt(i));
        if (s.codePointAt(i) > Character.MAX_VALUE) { i++; }  // UG!
        if (i+1 < s.length()) { System.out.printf("."); }
    }
}

E quem pensa em fazer isso? Ao lado de ninguém.

Quantos caracteres existem "\uD83D\uDCA9"? Um ou dois? Depende de como você os conta. É claro que o mecanismo regex lida com caracteres lógicos, portanto, um padrão ^.$será bem-sucedido e ^..$falhará. Essa loucura é demonstrada aqui:

String { U+61, "\u0061", "a" }  =~ /^.$/ => matched.
String { U+61, "\u0061", "a" }  =~ /^..$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" }  =~ /^.$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" }  =~ /^..$/ => matched.
String { U+DF, "\u00DF", "ß" }  =~ /^.$/ => matched.
String { U+DF, "\u00DF", "ß" }  =~ /^..$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" }  =~ /^.$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" }  =~ /^..$/ => matched.
String { U+3C3, "\u03C3", "σ" }  =~ /^.$/ => matched.
String { U+3C3, "\u03C3", "σ" }  =~ /^..$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" }  =~ /^.$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" }  =~ /^..$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" }  =~ /^.$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" }  =~ /^..$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" }  =~ /^.$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" }  =~ /^..$/ => matched.

Essa idiotice é tudo porque você não pode escrever o texto perfeitamente razoável \u1F4A9 , nem é claro que recebe qualquer aviso de que não pode fazer isso. Apenas faz a coisa errada.

Stoooopid.

Enquanto estamos nisso, toda a \uXXXXnotação é congenitamente com morte cerebral. O pré-processador Java ( sim, você me ouviu ) chega antes do Java, então você está proibido de escrever coisas perfeitamente razoáveis ​​como "\u0022", porque, quando o Java vê isso, seu pré-processador o transformou """, então você perde. Oh espere, não se estiver em um regex! Então você pode usar"\\u0022" muito bem.

Riiiiiiiight!

Você sabia que não há como o Java fazer uma isatty(0) ligação? Você nem tem permissão para pensar em tais pensamentos. Não seria bom para você.

E depois há toda a abominação do caminho de classe.

Ou o fato de que não há como especificar a codificação do seu arquivo de origem Java no mesmo arquivo de origem para não perdê-lo? Mais uma vez eu exijo saber: O QUE diabos eles estavam pensando‽‽‽

Pare a loucura! Não acredito que as pessoas suportam esse lixo. É uma piada completa. Prefiro ser um cumprimentador do Walmart do que sofrer os golpes e flechas da insanidade ultrajante em Java. Está tudo quebrado, e eles não apenas não podem consertar, mas não consertam.

Isso pelas mesmas pessoas engraçadas que se orgulhavam de uma linguagem que tornava ilegal ter uma printf()função. Puxa, isso certeza funcionou muito bem, não foi !?

Pura numbskulls. Tapa na puta é muito gentil para eles. Se eu quisesse programar em assembler, faria. Esta não é uma linguagem salvável. O imperador não tem nenhuma roupa.

Nós odiamos isso. Nós odiamos isso para sempre . Deixe morrer, morrer, morrer !


Haha, bom, eu não toco java porque é muito polido como você descreve. Quanto a \ uD83D ... bem, suponho que uma maneira melhor de dizer isso é que você prefere que as strings não sejam UTF-16, mas UTF-32. Se você aceitar UTF-16-ness, a regex fará a coisa certa; é a chamada .length que estraga tudo.
Roman Starkov

4
-1. Com exceção dos comentários regexp e escapes Unicode, nenhuma das coisas mencionadas é um elemento de sintaxe.
Jörg W Mittag

3
@ Jörg, você quer sintaxe? Está bem: Java permite que você coloque caracteres de controle, incluindo ESC e NUL, nos identificadores. WTH eles estavam pensando ???
Tbrist

4
@tchrist: Uau! Se algum dia eu escrever um programa Java novamente, todas as minhas variáveis terão nomes consistindo de números variados de caracteres de retrocesso ( ^H) :)
j_random_hacker

1
@tchrist, sentindo-se melhor agora?

16

Sintaxe de declaração de ponteiro de função em C e C ++:

(int)(*f)(int, int);

Isso declara um ponteiro de função chamado fcujo pontapé pode levar dois se intretornar um int.

Eu preferiria uma sintaxe como esta:

f: (int, int) => int

Digamos que você queira declarar um ponteiro de função gcujo pontapé pode levar dois se intuma função de inte intpara inte retornar um int.

Com a notação C ou C ++, você a declararia como:

(int)(*g)(int, int, int(int, int));

Com a notação proposta acima, pode-se declarar a mesma coisa que:

g: (int, int, (int, int) => int) => int

O último é IMO muito mais intuitivo.


Além: A linguagem de programação chamada OOC corrige esta sintaxe (e vários outros problemas sintáticos em C e C ++). Confira sua página inicial aqui .


Concordo, alguns "C simples" / "C ++" não o suportam ou com sintaxe diferente. Uma sintaxe especial ajuda a indicar quando um recurso de linguagem de programação é suportado. É por isso que o C # adicionou a sintaxe "delegar".
umlcat

Os delegados não são apenas açúcar sintático, porque eles também armazenar o objeto (ao contrário de ponteiros de função membro C ++, que têm ainda pior sintaxe de ponteiros de função regulares)
Tamás Szelei

14

Verbosidade em Java.

ou seja:

public static final int 

6
Comparado com? (15 caracteres)
TheLQ

7
Comparado com: const intpor exemplo.
OscarRyz 6/09/10

11
"público final estático int x = 4;" comparado com "x = 4" em Haskell.
Jared Updike

24
Isso não é verbosidade. Tente escrever a+(b*c)/d*e+f/g^20usando BigIntegerem Java. Por que esse idioma não permite sobrecarga do operador?
MAK

4
@ Michael: os programadores que precisam ser protegidos de si mesmos a esse custo podem se proteger melhor (e reduzir a dor de todos os outros) por não programarem: D.
MAK

12

\ we \ wouldnt \ fixar \ nossa \ sintaxe do espaço para nome do analisador no PHP

A sintaxe não é apenas feia, mas também gera confusão quando os desenvolvedores mais novos precisam pensar em namespaces em strings. (O PHP interpola barras invertidas em seqüências de caracteres com aspas duplas como seqüências de escape. Tentar representar um espaço para nome como \you\should\never\do\thatem uma sequência de aspas duplas em vez de uma sequência de aspas simples levará a novas linhas, guias e desastres.)


Sim, alguém pensou em uma maneira melhor :: de fazer isso, mas o PHP insiste que todo operador deve ser diferente. Estou curioso para saber qual é o problema do uso indevido aqui.
Alan Pearce

Aceita. PHP requer namespaces, mas essa sintaxe
estraga

9

Eu desprezo o fato de que o aparelho pode ser opcional após uma declaração if / while / for.

Especialmente quando vejo código como,

if (...)
    for(...)
        ... One line of stuff ...

Por favor, apenas coloque os aparelhos e termine com isso.


6
Hmm .. isso depende. Para "Abortar Ifs", que apenas verifica uma condição e retorna um código de erro (ou lança uma exceção), prefiro não ver o aparelho.
Billy ONeal

4
Concordo que você se limite a casos extremos de vários níveis, mas sua declaração é muito geral. Existe uma grande utilidade na capacidade de ter formulários curtos para ifs e loops simples de instrução única.
Timwi

2
Minha regra: somente se uma declaração exigir várias subestações ou se contiver essa declaração, deve ser colocada entre chaves. Assim, for (...) while (...) if (...) { x(); y(); }é melhor reescrito como for (...) { while (...) { if (...) { x(); y(); } } }, com recuo apropriado, é claro.
Jon Purdy

6
Eu sou o contrário - eu desprezo as pessoas que insistem em usar aparelho quando são completamente desnecessárias. Apenas aprenda a programar.
Jerry Coffin

3
Eu realmente gosto dos colchetes, mesmo em declarações if únicas. Isso me faz seguir melhor o fluxo de um programa.
Ricardo Santos

9

O VBScript não possui operadores lógicos

Diferente de quase toda linguagem sensata, o VBScript usa operadores bit a bit em vez de operadores lógicos. O que isso significa na prática? Bem, como Eric Lippert aponta :

If Blah = True Then Print "True!" Else Print "False!"

e

If Blah Then Print "True!" Else Print "False!"

NÃO são iguais no VBScript!

Pior ainda, isso significa que não há avaliação de curto-circuito no VBScript, de modo que a instrução a seguir irá travar seu programa se BlahforNothing

If (Not Blah Is Nothing) And (Blah.Frob = 123) Then
...

É isso mesmo, o VBScript avaliará as duas partes da comparação AND, mesmo que a primeira seja falsa! Apenas deixe isso afundar ...


3
Até o dia em que você procurou um bug dentro de um If x Then ... If Not x Then ... End If ... End Ife descobriu que x é 2, você realmente não programou no VB / VBScript.
configurador

7

EDIT: Após a discussão nos comentários, decidi atualizar esta resposta para me explicar melhor.

Eu realmente odeio a maneira como os ponteiros de função aparecem em C. Normalmente, qualquer declaração de variável se parece com uma tupla de: type varname; Declarações de ponteiros de função, por outro lado, parecem com uma declaração da função com * antes do nome da função. Eu posso aceitar isso como uma descrição de um tipo de ponteiro, mas em C isso declara o tipo e o nome de uma variável desse tipo. Isso me parece inconsistente porque as declarações de tipo são diferentes das declarações de variáveis. struct myStruct{int X; int Y;}define apenas um tipo, que não define uma variável chamada myStruct. Da mesma forma, não vejo razão para as declarações de tipo e variável serem agrupadas em uma instrução atômica em ponteiros de função, nem aprecio o desvio da type varname;estrutura.

Alguém apontou que é consistente com alguma regra em espiral, e esse pode ser o caso, mas a marca de uma boa sintaxe é que ela é auto-explicativa e sua lógica interna é óbvia. A regra da espiral não é óbvia de forma alguma.


1
É consistente com o restante do idioma, então talvez sua queixa seja sobre a sintaxe dos declaradores C em geral? Você prefere a sintaxe usada no Go ?
finnw 3/09/10

Consistente de que maneira? Geralmente vai: digite varname; E quando criamos um novo tipo composto, como uma estrutura, primeiro vem a declaração, talvez com um typedef, e depois criamos uma variável desse tipo. Quando declaramos um ponteiro de função, é int (* foo) (int arg1, int arg2), que é então usado como o tipo de argumento passado para uma função: void newFoo (int (* foo) (int arg1, int art2) )) .... e como uma variável: foo = a_compatible_func; Eu acho que uma declaração de função primeiro, e depois uma declaração var seria mais consistente, assim: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
EpsilonVector

É por isso que você conseguiu typedef.
precisa saber é o seguinte

4
@EpsilonVector: costumo concordar que a sintaxe do ponteiro de função é desagradável, mas existe uma regra simples a seguir que facilita a leitura. A regra da espiral no sentido horário (talvez você a tenha visto?): C-faq.com/decl/spiral.anderson.html
greyfade

1
EpsilonVector: Não tenho certeza do que você esperaria de uma declaração de variável de ponteiro declarar outro que não o nome da variável.

6

Ponto e vírgula no VBScript - ou a falta dela

Passo o dia inteiro trabalhando em idiomas que esperam ponto e vírgula no final de cada linha. Adicione um ao final da linha no VBScript e seu código não será mais executado.


4
votar com antecedência, não porque eu particularmente goste de ponto-e-vírgula, mas porque eu realmente odeio o modo como o VB incentiva linhas realmente longas, tornando as quebras de linha tão inconvenientes.
Shog9

6

Argumentos de entrada / saída. Sou a favor de argumentos (que bom que sou), argumentos fora também são bons, mas um argumento que deve transmitir esses dois estados me irrita.

O que eu alvo aqui são funções que recebem entrada de um parâmetro e substituem essa entrada com alguma saída. Não há problema em passar um objeto por referência para atualizá-lo. Mas, principalmente para tipos primitivos, pegar um objeto, usá-lo e depois alterá-lo completamente, não é certo para mim. Você não deve alterar o significado do argumento através de uma entrada.


Que idioma você tem em mente? Se C #, então eu discordo que é irritante porque é sempre explícito (ao contrário do C ++.) Também não conheço nenhuma linguagem mainstream em que você seja forçado a declarar argumentos como in / out.
finnw

@finnw Eu nunca vi uma linguagem onde você tinha a dizer inpara inargumentos tanto, eu só estou falando sobre eles. Além disso, na minha opinião, nada pode desculpar um argumento de entrada / saída, e torná-los explícitos não alivia a dor. Não deve haver razão para inicializar uma variável local com um valor útil para a função, e ter essa mesma variável e, de repente, conter o que a função decidiu colocar lá. Esses dois devem ser distintos. Sempre.
precisa saber é o seguinte

Desculpe, eu não estava muito claro lá. Eu pretendia dizer "eu não conheço nenhum idioma em que todos os argumentos estejam implicitamente in + out", ou seja, você não é forçado a usar esse recurso, mas há casos de uso legítimos (por exemplo, atualizar um em structque o novo valor depende do valor de outro campo do mesmo struct.)
finnw

Objetos passados ​​por referência (como instâncias de classobjetos em C #) sendo modificados por uma função são bons para mim. Além de não gostar de estruturas não constantes, passar um structcom a refpalavra-chave para atualizá-la também é bom. O que eu realmente odeio é quando a entrada é substituída pela saída. O melhor exemplo que consigo pensar é na acceptfunção do soquete de Berkeley : ele precisa de um socklen_t*argumento que, na entrada, deva conter o tamanho do struct sockaddr*que você passou; e na saída, conterá o número de bytes que foram gravados nele. Isso deve ser criminoso.
zneak

Concordo que isso é ruim (IIRC, algumas funções de E / S do Win32 fazem o mesmo), mas isso é mau uso do recurso (a chamada de função altera o significado da variável passada, não apenas seu valor) e isso não significa que o recurso em si é ruim.
finnw 3/09/10

6

Declarações de matriz em C e C ++.

Normalmente, uma declaração variável é do formato type variable_name. Você pode facilmente ler essas declarações da esquerda para a direita. Mas, int foo[size]a princípio, parece que ele está declarando foocomo int, e então você lê mais e vê os foo do tipo "matriz de números inteiros". int[size] foolê muito melhor.

E eu também odeio quando programadores declarar ponteiros como este por um motivo semelhante: int *foo. Por alguma razão eu não descobri, esse é o típico jeito que está escrito.


1
Re declarações do ponteiro: elas são escritas assim porque o ' ' se liga ao nome da variável, não ao tipo. O int* a, b;mesmo * não declara ae bcomo ponteiro; somente aé. Por isso, é melhor escrevê-lo como int *a, b;(ou ainda melhor escrevê-los como duas declarações).
Steve Melnikoff

Bom ponto. É uma pena *que não se ligue ao tipo.
Jacob

2
E isso é para não dizer nada sobre indicadores de função ... void(int) *f;? Não:void (*f)(int);
Nota para si mesmo - pense em um nome

No C ++ moderno, há muito pouca necessidade de ponteiros e matrizes.
Fredoverflow 26/09/10

2
@ Steve Melnikoff: Embora eu tenha marcado esta resposta com +1, acho que a int* a, b;questão que você mencionou é muito mais flagrante.
Jrandom_hacker

5

Parametrização redundante em Java:

HashMap<String,HashMap<String,String>> foo = new HashMap<String, HashMap<String, String>>();

Que outro tipo de parametrização o compilador acha que foo poderia ter?


4
Espero que você esteja ciente da inferência de tipo (limitada) do Java? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
finnw

1
Java 7:HashMap<String,HashMap<String,String>> foo = new HashMap<>();
Bart van Heukelom

5
Bem, ele pode ter qualquer tipo que você quiser, os tipos são apagados de qualquer maneira ...
configurator

Falta de inferência de tipo, você quer dizer?
missingfaktor

What other type parameterization does the compiler think foo could have?- Por alguma razão, as coisas são do tipo bruto - como se alguém sensato misturasse tipos brutos e parametrizados.
Maaartinus

5

Como as pessoas já se queixaram de =vs. ==, deixe-me apontar uma alternativa muito pior. O PL / eu tinha ambos :=e =, mas quando algo era "obviamente" uma tarefa, isso permitiria que você se =desse bem. Usando:= permite forçar algo a ser uma atribuição em uma situação em que o compilador o interpretaria como uma comparação.

Infelizmente, o compilador nem sempre decidiu as coisas da maneira que você poderia esperar. Considere apenas um exemplo óbvio:

A = B = 0;

Agora, para a maioria das pessoas familiarizadas com a maioria das linguagens "comuns", o significado disso é bastante óbvio - atribua 0 a A e B. PL / I é apenas um pouco ... diferente. Por razões conhecidas apenas pelos designers (insanos) da linguagem, o primeiro =é interpretado como uma tarefa, mas o segundo= é interpretado como uma comparação. Portanto, isso compara B a 0 e atribui o resultado dessa comparação a A (seguindo a convenção no estilo C que "false" resulta em 0 e "true" em 1).

Portanto, se B era 0, então A se torna 1. Caso contrário, A se torna 0. Em outras palavras, em vez de atribuir o mesmo valor a A e B, isso realmente garante que A não possa ter o mesmo valor que B.

Conclusão: embora o estilo C / C ++ / PHP pareça inicialmente uma dor, a alternativa é muito pior 1 .

1 Bem, tecnicamente, há outra alternativa: o estilo Pascal, onde =sempre significa comparação e atribuição sempre exige :=. Depois de usar isso por um tempo, é bastante óbvio (pelo menos para mim) que a tarefa é bastante mais comum do que a comparação. Se você precisar de "coisas" extras para desambiguar os dois, você definitivamente deve manter as tarefas limpas e simples e exigir o "grunge" extra nas comparações, não vice-versa.


1
Eu até proporia usar ==pela igualdade e :=pela atribuição. Dessa forma, você tem mais para digitar, mas evitar os solitários =ajuda a evitar bugs.
Maaartinus

@maartinus: pelo menos para mim, isso soa como o pior possibilidade absoluta, mas a vida é assim ...
Jerry Coffin

3

Perl

  1. Desejo que Perl me deixe escrever if($x < 10) do_something();. No momento, você deve escrever isso como do_something() if($x < 10);ou como if($x < 10) { do_something(); }.

9
do_something() if ($x < 10);não é tão ruim assim.
Zneak 03/09/10

Não é, e em muitos casos é muito mais limpo do if(..) ...que inicializar, pois você pode obter todas as expressões alinhadas à direita. Mas há momentos em que realmente quero dizer if($x < 10) do_something();, e é uma pena que Perl não me permita.
Gaurav

7
É lamentável até você escrever if ($x<10) do_something(); and_call_me(); e depois se perguntar por que você nunca recebe uma ligação. Desejo que C e família exijam chaves, para evitar esse tipo de erro.
ASHelly #

2
@ Ashelly: ou por que você sempre recebe uma ligação, na verdade.
zneak

1
@ zneak Exceto não elses. (Eu desejo que tem EXPR1 if COND else EXPR2como Python tem)
Ming-Tang

3

reinterpret_cast<unsigned long>em c ++. Essa operação é útil para lidar com APIs estrangeiras e garantir precisão numérica. Por que seria tão difícil digitar e tão feio de se olhar?


17
É feio lembrar que você deve se esforçar para escrever um código que não o exija. :)
greyfade

Para mim, esse é um bom argumento teórico da ciência da computação, mas, na minha experiência, é útil demais para evitar (no entanto, grande parte da minha experiência é simples e antiga C, então provavelmente tenho um viés).
precisa saber é o seguinte

5
Não é realmente um argumento teórico de CS: o uso de um reinterpret_castem C ++ é um cheiro de código muito forte. 99% do tempo, quando você está prestes a usá-lo, é provável que você não precise - você provavelmente fez algo errado. No outro 1% do tempo, você está em interface com C. reinterpret_castquebra o sistema de tipos para fazer algo funcionar quando, de outra forma, não pode. Isso geralmente é uma coisa ruim.
greyfade

3

A construção for ... in em JavaScript e a construção foreach em PHP ao fazer um loop sobre matrizes. Ambos facilitam a gravação de bugs do que o código correto.


3
Uau, isso é besteira. "Do que o código correto". Vá embora.
Jonathan Sterling

Se eu tiver que escrever um código extra para usá-lo com segurança, é mais fácil usá-lo errado no meu livro. For ... in exige verificações extras para garantir que você não esteja iterando sobre os objetos do protótipo, e foreach exige que você limpe as referências posteriormente ou corra o risco de sobrescrever o último valor na matriz.
Joeri Sebrechts

o foreach com a mudança de referências (& operador) é um bug famosa ...
umlcat

1
Estou confuso, pensei que era de conhecimento geral que a construção "for..in" em javascript está quebrada ... por que isso é ofensivo?
Lvilnis

2

Ponteiros de matrizes ou matrizes de ponteiros em C / C ++. Eu ainda estou confuso sobre isso.


3
Leia o tipo para trás. int[]*é um ponteiro para uma matriz de números inteiros e int*[]é uma matriz de ponteiros para números inteiros. Funciona bem com consts demasiado: int* consté um ponteiro constante para inteiros, enquanto que const int*e int const*são apontadores para inteiros constantes (ou constantes inteiras).
zneak

@ zneak: "Direita para a esquerda" não funciona, veja a regra mencionada "espiral no sentido horário" / "de dentro para fora" .

Ou, apenas use typedefs e não há confusão.
Billy ONeal

No C ++ moderno, há muito pouca necessidade de ponteiros e matrizes.
Fredoverflow 26/09/10

4
@ tchrist: Não é verdade. int (*p)[10];declara pser um ponteiro para uma matriz de 10 polegadas. Se sizeof (int) == 4, então p++, avançará pem 40.
j_random_hacker 29/11


1

Javascript / Java etc, é igual a comparação, por exemplo, se (a == 1)

Quantas vezes escrevo se (a = 1)?

Como humano, eu li isso perfeitamente. Mas o danado intérprete / compilador diz: "ei, atribuirei 1 a a, depois verifico se a é igual a 1 e você acreditaria que sim!

Me leva até a parede.

se (a == 1) é muito menos legível, e o intérprete / compilador deve saber o que quero dizer; muitos outros idiomas menores (VB) vêm trabalhando com êxito há centenas de anos.


O que if (a = true)deveria significar?
Tom Hawtin - defina

2
A atribuição simplesmente não deve retornar um valor. Às vezes é útil, mas na maioria dos casos é apenas uma dor no pescoço.
configurator

em Javascript, o JSLint pegará esse para você.
Zachary K

O problema é que a atribuição em condições pode ser útil. Acho <tt> while (element = list-> next ()) </tt> bastante legível. Portanto, não tenho certeza se gostaria de removê-lo.
Inca

3
@ Tom: Significa que você não entende booleanos. Se você quis dizer if (a == true), basta escrever if (a). Se você quis dizer a = true, a ifdeclaração é redundante.
dan04 27/02


0

structPointer->memberem C / C ++. Pode ser bom para ler o código de outra pessoa, mas não gosto. Dois caracteres em vez de um ... que desperdício de espaço!


2
Infelizmente, ele deve ser diferenciado ., o que se aplica aos membros de um objeto não-ponteiro. Sintaxe ambígua é ruim, mmmkay?
greyfade

2
@greyfade: Sim! Como o compilador não pode usar suas regras de sistema de tipo para saber quando você está usando um tipo de ponteiro para estrutura e aplicar a desreferência implicitamente. Não, isso é loucura! (E ainda assim, de alguma forma, você pode receber uma mensagem de erro quando errar.) Não há nada ambíguo na sintaxe. É apenas C estar uma bagunça de cabeça cheia, como sempre. Delphi faz dereferences implícitas muito bem, se você está realmente trabalhando em cantos escuros que exigem ponteiros-to-registros, por isso certamente pode ser feito sem confundir um analisador ...
Mason Wheeler

5
@Mason: E quanto a casos como shared_ptr, onde ->acessa o tipo contido e .acessa propriedades do shared_ptrpróprio? Sinto muito, mas eu discordo completamente aqui.
Billy ONeal

2
poderia ser pior. Pode ser PHP, onde você precisa usar ->para acessar membros de qualquer coisa .
Carson Myers

1
@ maaartinus: Qualquer código que dependa muito dessa ordem não óbvia de operações não é um código que eu escreverei.
Billy ONeal

0

Código multi-linhas Scala entre parênteses

Por exemplo:

class Foo(
         val bar: String,
         val baz: Int,
         val bing: String,
         val bong: Boolean
 ) extends Model {
   // body here
 }

O que você realmente obtém é fantástico. Ele gera o construtor e os getters e setters para você. Mas com certeza é feio e quebra todos os meus modelos mentais de como recuar código e basicamente me deixa como se eu estivesse em uma espécie de sanduíche bizarro com Java de um lado e Lisp do outro. (Oh, espere ... esse é o ponto de Scala.)


Estou confuso - você quer dizer a parte entre parênteses ( val bare assim por diante) ou a parte entre chaves (a parte a seguir extends Model)? (Não existem suportes em que o código)
Billy ONeal

3
A parte entre parênteses. Eu sou inglês. Nós nos referimos a eles como colchetes, caramba, porque nessa situação eles não estão cumprindo um papel entre parênteses.
Tom Morris

2
Não parece tão ruim se recuado dessa maneira: pastebin.com/h9qC8XGg
missingfaktor 15/10/10

Acho mais legível escrever essas listas de parâmetros do construtor horizontalmente, especialmente quando eu tenho apenas alguns parâmetros.
MJP

Parece um método para mim. Como Simula. Boa velha escola.
Tom Hawtin - tackline
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.