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?
programming-languages
syntax
Timwi
fonte
fonte
Respostas:
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)
Exemplo:
fonte
Sintaxe de Java-bean devido à falta de propriedades de C #
GAH !!!
Problemas que tenho com isso
getX
,getY
,getZ
,getAnotherAnnoyingField
,getWhyIHateJavaBeans
,getThisIsVerbose
,getGAH
... ah lá está,hashCode
.fonte
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.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.
fonte
A
switch
instrução (em C, C ++, C #, Java etc.)Aqui está um exemplo de por que considero altamente inconveniente:
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 extrabreak
. Isso seria muito melhor: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 umaswitch
declaração a ordem dos rótulos dos casos não importa, mas em umif
/else
isso importa.fonte
goto
ou similar), como já é o caso em C #.case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;
.break
era o padrão e apenas o avanço precisava ser especificado. Não há mais necessidade de lembrar de comentar! :)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:
fonte
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.
Você pode usar dois pontos para colocar dois comandos em uma linha, mas rapidamente fica confuso no código real.
fonte
Dim Hurp As New Collection
, se acessarHurp
quando se referirNothing
, será magicamente inicializado antes do acesso. Se você o definir explicitamenteNothing
e tocar novamente, ele será ressuscitado ... suspiro!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.
fonte
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
$needle
e 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 :
Curiosamente, o PHP parece ser internamente consistente com essas ordenações, pois todas as funções de string parecem usar
$haystack, $needle
enquanto 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!fonte
$needle
,$haystack
pois lembra a maneira de dizer encontrar uma agulha no palheiro .strstr
. Tão lindamente sem sentido.Python
self
parâmetro nas definições de método da instânciafonte
self
acontece com facilidade e custa tempo.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:
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
\n
estã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:
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:
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: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
\uXXXX
notaçã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 !
fonte
^H
) :)Sintaxe de declaração de ponteiro de função em C e C ++:
Isso declara um ponteiro de função chamado
f
cujo pontapé pode levar dois seint
retornar umint
.Eu preferiria uma sintaxe como esta:
Digamos que você queira declarar um ponteiro de função
g
cujo pontapé pode levar dois seint
uma função deint
eint
paraint
e retornar umint
.Com a notação C ou C ++, você a declararia como:
Com a notação proposta acima, pode-se declarar a mesma coisa que:
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 .
fonte
Verbosidade em Java.
ou seja:
fonte
const int
por exemplo.a+(b*c)/d*e+f/g^20
usandoBigInteger
em Java. Por que esse idioma não permite sobrecarga do operador?\ 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\that
em uma sequência de aspas duplas em vez de uma sequência de aspas simples levará a novas linhas, guias e desastres.)fonte
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,
Por favor, apenas coloque os aparelhos e termine com isso.
fonte
for (...) while (...) if (...) { x(); y(); }
é melhor reescrito comofor (...) { while (...) { if (...) { x(); y(); } } }
, com recuo apropriado, é claro.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 :
e
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
Blah
forNothing
É isso mesmo, o VBScript avaliará as duas partes da comparação AND, mesmo que a primeira seja falsa! Apenas deixe isso afundar ...
fonte
If x Then ... If Not x Then ... End If ... End If
e descobriu que x é 2, você realmente não programou no VB / VBScript.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 chamadamyStruct
. 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 datype 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.
fonte
typedef
.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.
fonte
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.
fonte
in
parain
argumentos 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.struct
que o novo valor depende do valor de outro campo do mesmostruct
.)class
objetos 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 umstruct
com aref
palavra-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 é naaccept
função do soquete de Berkeley : ele precisa de umsocklen_t*
argumento que, na entrada, deva conter o tamanho dostruct sockaddr*
que você passou; e na saída, conterá o número de bytes que foram gravados nele. Isso deve ser criminoso.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á declarandofoo
como int, e então você lê mais e vê os foo do tipo "matriz de números inteiros".int[size] foo
lê 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.fonte
int* a, b;
mesmo * não declaraa
eb
como ponteiro; somentea
é. Por isso, é melhor escrevê-lo comoint *a, b;
(ou ainda melhor escrevê-los como duas declarações).*
que não se ligue ao tipo.void(int) *f;
? Não:void (*f)(int);
int* a, b;
questão que você mencionou é muito mais flagrante.Parametrização redundante em Java:
Que outro tipo de parametrização o compilador acha que
foo
poderia ter?fonte
HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
HashMap<String,HashMap<String,String>> foo = new HashMap<>();
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.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:
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.fonte
==
pela igualdade e:=
pela atribuição. Dessa forma, você tem mais para digitar, mas evitar os solitários=
ajuda a evitar bugs.Perl
if($x < 10) do_something();
. No momento, você deve escrever isso comodo_something() if($x < 10);
ou comoif($x < 10) { do_something(); }
.fonte
do_something() if ($x < 10);
não é tão ruim assim.if(..) ...
que inicializar, pois você pode obter todas as expressões alinhadas à direita. Mas há momentos em que realmente quero dizerif($x < 10) do_something();
, e é uma pena que Perl não me permita.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.else
s. (Eu desejo que temEXPR1 if COND else EXPR2
como Python tem)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?fonte
reinterpret_cast
em 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_cast
quebra o sistema de tipos para fazer algo funcionar quando, de outra forma, não pode. Isso geralmente é uma coisa ruim.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.
fonte
Ponteiros de matrizes ou matrizes de ponteiros em C / C ++. Eu ainda estou confuso sobre isso.
fonte
int[]*
é um ponteiro para uma matriz de números inteiros eint*[]
é uma matriz de ponteiros para números inteiros. Funciona bem comconst
s demasiado:int* const
é um ponteiro constante para inteiros, enquanto queconst int*
eint const*
são apontadores para inteiros constantes (ou constantes inteiras).int (*p)[10];
declarap
ser um ponteiro para uma matriz de 10 polegadas. Sesizeof (int) == 4
, entãop++
, avançaráp
em 40.O fato de o Python confiar na formatação de texto.
fonte
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.
fonte
if (a = true)
deveria significar?if (a == true)
, basta escreverif (a)
. Se você quis dizera = true
, aif
declaração é redundante.Verbosidade em classes anônimas Java. Esperemos que seja corrigido em breve.
fonte
structPointer->member
em 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!fonte
.
, o que se aplica aos membros de um objeto não-ponteiro. Sintaxe ambígua é ruim, mmmkay?shared_ptr
, onde->
acessa o tipo contido e.
acessa propriedades doshared_ptr
próprio? Sinto muito, mas eu discordo completamente aqui.->
para acessar membros de qualquer coisa .Código multi-linhas Scala entre parênteses
Por exemplo:
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.)
fonte
val bar
e assim por diante) ou a parte entre chaves (a parte a seguirextends Model
)? (Não existem suportes em que o código)