¿Qué elemento de sintaxis odias más en un lenguaje de programación que utilizas con frecuencia? [cerrado]


27

No importa cuánto te guste un lenguaje de programación, siempre hay algunos detalles que no son tan buenos como podrían ser.

En esta pregunta, me gustaría centrarme específicamente en los elementos de sintaxis. En un lenguaje de programación que usa con frecuencia (tal vez su lenguaje de programación favorito, o quizás el que se ve obligado a usar en el trabajo), ¿qué elemento de sintaxis encuentra más ilegible, poco claro, inconveniente o desagradable?


@Nathan Taylor, no para esta pregunta, sino para otra pregunta .
finnw

¿Esta pregunta se modificó? Porque cuando respondí, no estaba enfocado en "elementos de sintaxis" ... Tendré que modificar mi respuesta ahora.
Talvi Watia

@Talvi: No, se trataba de sintaxis desde el principio.
Timwi

@Timwi raro, debe ser un caso de 'responder una pregunta pensando que era diferente' entonces.
Talvi Watia

Si puede votar y cree que esta es una pregunta útil o tiene respuestas útiles a continuación, vote por favor. Los sitios de StackExchange necesitan votos para construir una buena comunidad. Puedes dar 30 votos por día, no los desperdicies. Especialmente usuarios con alta reputación y votos de bajo recuento dados, lean esto: meta.programmers.stackexchange.com/questions/393/…
Maniero

Respuestas:


39

Inserción de punto y coma en JavaScript.

Realmente no me ha mordido a menudo, pero es una idea tan fenomenalmente mala que me da vueltas la cabeza.


Aquí están las reglas (de ECMA-262 Sección 7.9)

  1. Cuando el programa contiene un token que no está permitido por la gramática formal, se inserta un punto y coma si (a) hay un salto de línea en ese punto, o (b) el token inesperado era una llave de cierre.
  2. Cuando se alcanza el final de un archivo, si el programa no se puede analizar de otra manera, se inserta un punto y coma.
  3. Cuando se encuentra una "producción restringida" y contiene un terminador de línea en un lugar donde la gramática contiene la anotación "[no hay LineTerminator aquí]", se inserta un punto y coma.

Ejemplo:

return 1; // returns 1

return
1; // returns undefined

2
JavaScript: El lenguaje de programación más incomprendido del mundo ~ Douglas Crockford
pramodc84

Sí, muchos esperan que JavaScript sea un "lenguaje de forma libre", pero no lo es.
Andreas Rejbrand

13
Tiene sentido una vez que se da cuenta de que JavaScript fue diseñado para crear HTML, que también tiene un largo historial de intentar interpretar lo que su código "realmente significa" cuando no es sintácticamente válido. (Consulte el Principio de robustez en algún momento, el mayor desastre en la historia de la informática).
Mason Wheeler

77
Este tipo de errores, para mí, es un olor a código que el programador es descuidado y nunca ha trabajado con la mayoría de los lenguajes "estrictos" formales que normalmente causarían un error de sintaxis para dejar el punto y coma fuera.
Talvi Watia

77
Wohoo, finalmente, alguien más que también piensa que el Principio de Robustez es un desastre que ha convertido al HTML en un desastre total.
Roman Starkov

39

Sintaxis de Java-Bean debido a la falta de propiedades 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 tengo con esto

  • Demasiado código : tenga un campo documentado, un método getter documentado y un método setter documentado. Este ejemplo extremadamente básico tiene 20 líneas de código para un solo propiedad
  • Listas de métodos Clutter - "Let Me parece que el método, la mano en: getX, getY, getZ, getAnotherAnnoyingField, getWhyIHateJavaBeans, getThisIsVerbose, getGAH... ah ahí está,hashCode .
  • Múltiples áreas de documentación conducen a documentación deficiente, desactualizada o faltante , lo que es molesto al tratar de comprender qué hace el código
  • Tan molesto que un tercero tuvo que crear un complemento para hacerlo fácilmente : Spoon , Shark , entre otros.

99
Una vez más, cuando el código es tan detallado que necesita herramientas de generación automática, algo está mal. Soy un tipo de NetBeans, pero también tiene la capacidad de generar automáticamente getters y setters. Pero Javadoc no se sincroniza, todavía es detallado, todavía
abarrota a Javadoc

11
Si necesita captadores para todo, entonces algo está mal con el código del cliente .
finnw

77
Tener captadores y colocadores rompe la encapsulación. El campo bien podría ser public. Los miembros deben ser privados y deben ser manipulados con sensatez por la clase con lógica de nivel superior, no con captadores y definidores del código del cliente.
greyfade

66
@greyfade: si es público, no puede cambiar fácilmente lo que hace el código de configuración (tendrá que cambiar todo el código que establece el campo desde el exterior).
Bart van Heukelom

3
@SHiNKiROU: ¿Java se ve limpio? ¡Nunca antes había escuchado eso! Mi queja principal con Java es el hecho de que una cosa aparentemente simple requiere docenas de líneas de código que necesito ignorar mentalmente.
configurador

33

Sensibilidad de espacios en blanco.

Python me molesta a este respecto. Es decir, Dejé sangría correctamente todos modos, pero me molesta que yo debería tener al. Hacer que la presentación sea parte de la sintaxis me irrita.


8
aprenderás a amarlo
user10008

2
sintaxis es presentación
Winston Ewert

32

La switchdeclaración (en C, C ++, C #, Java, etc.)

Aquí hay un ejemplo de por qué me resulta muy inconveniente:

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

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

Esto no se compila porque la variable ise vuelve a declarar en el mismo ámbito. Esto parece un detalle menor, pero me muerde muy a menudo. Puedo agregar llaves para mitigarlo, pero hubiera sido bueno si las llaves hubieran sido parte obligatoria de la sintaxis, y no hubiera un nivel de sangría adicional redundante. También realmente odio tener que escribir el extra break. Esto sería mucho mejor:

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

Esto hace que se parezca más a una if/ elsecadena, lo cual es bueno porque también es semánticamente similar. Al menos en C # todavía no sería lo mismo sin embargo, debido a que en un switchcomunicado que el orden de las etiquetas de caso no importa, pero en un if/ elselo hace.


1
Desafortunadamente, su sintaxis mejorada elimina lo que podría decirse que es la característica más importante del conmutador en la mayoría de estos idiomas: Fall-through. El "Dispositivo de Duff" en C es un ejemplo perfecto del valor de esta "característica errónea" en particular. También es común en los lenguajes tipo C usar fall-through en intérpretes y programas similares.
greyfade

77
No, no lo elimina. Solo requiere que se haga más explícito (usando gotoao similar), como ya es el caso en C #.
Timwi

8
@greyfade: cualquier código que use el dispositivo de duff en C necesita una muerte horrible Los compiladores toman mejores decisiones sobre este tipo de cosas que tú.
Billy ONeal

44
@greyfade: Delphi consigue en torno al tema de múltiples valor simplemente permitiendo múltiples índices en el caso: case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;.
Frank Shearar

3
@jkerian: Ahora imagine que breakera el valor predeterminado y solo era necesario especificar el avance. ¡Ya no necesitas recordar comentarlo! :)
Timwi

27

Declaraciones de matriz en VB.NET

Siempre logro olvidar que al inicializar arreglos fijos en VB.NET, está especificando el límite superior del arreglo y no el número de elementos como en C / C ++, PHP o Java. Además de VB6 (no iremos allí ...), no puedo pensar en otro idioma que lo haga de esta manera:

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

Creo que todos los lenguajes BASIC hacen esto ... Sé lo que hacen BASIC y QBasic originales.
Michael K

OMG que es verdaderamente horrible .... 1
mikera

25

VB6 - Declaración y asignación de variables separadas

La mayoría de los idiomas le permiten declarar una variable y asignarla en una línea de código; VB6, por otro lado, te obliga a usar dos.

Dim i as Integer
i = 0

Dim derpderp as Collection
Set derpderp = new Collection

Puede usar dos puntos para colocar dos comandos en una línea, pero rápidamente se vuelve desordenado en el código real.

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

77
+1 por tener que usar VB6 como su idioma más frecuente.
Walter

99
Lo uso a diario ... sollozo.
systempuntoout

¿Pascal no tiene una sintaxis similar? Siempre pensé que era desagradable.
greyfade

1
Hay un caso especial: si usted Dim Hurp As New Collection, si accede Hurpcuando se refiere Nothing, se iniciará mágicamente antes del acceso. Si lo configura explícitamente Nothingy lo toca de nuevo, se resucita ... ¡jadeo!
Jeffrey Hantin

1
+ 1 millón para Derp. Derp de derp de tiddly tum de derp.
MVCylon

24

Comentando en CSS

//no comenta líneas de código como lo hace en muchos otros idiomas, como PHP y Javascript. Aunque /* this is commented out */funciona, prefiero usar //.

Es una molestia, porque la mitad del tiempo me olvido de que estoy editando CSS y luego tengo que volver y corregir el error.


Pensarías hoy en día que CSS sin formato se consideraría código objeto.
Tom Hawtin - tackline

// funciona bien para comentar CSS. Lo hago todo el tiempo. Todo lo que realmente estoy haciendo es escribir basura. pero parece funcionar saltando la línea no analizable.
MVCylon

1
@MVCylon Si usa // para comentar una línea, cualquier cosa después de esa línea siguiente también se omite. {dentro de ese estilo específico} En otras palabras, FALLA porque esas líneas no deben omitirse.
Talvi Watia

20

PHP - ordenamiento consistente de argumentos

PHP tiene una serie de funciones útiles para realizar prácticamente todas las operaciones que pueda imaginar en una matriz o cadena. Muchas de estas operaciones requieren el uso de a $needley a$haystack , pero diferentes funciones las toman en diferentes órdenes. ¡Qué función requiere qué argumentos es uno de esos hechos que mi cerebro se niega a absorber, sin importar con qué frecuencia los encuentre!

Tome las funciones in_array y 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, PHP parece ser internamente consistente con estos ordenamientos en que todas las funciones de cadena parecen usarse $haystack, $needlemientras que las funciones de matriz son al revés, pero esto puede llevar un poco de tiempo acostumbrarse a alguien nuevo en PHP. Hay una buena publicación en ExpressionEngine que habla sobre esta peculiaridad en particular con más detalle, así como una discusión sobre la lista de errores de PHP , que presenta una respuesta muy corta del equipo de PHP.

helly@php.net
Use un IDE decente entonces.

2
Es más fácil recordar el orden $needle, $haystackya que recuerda la forma de decir encontrar una aguja en un pajar .
kiamlaluno

3
Protip: en las funciones de matriz, la aguja es lo primero. En las funciones de cadena, el pajar es lo primero.
GSto

17
Me encanta el nombre strstr. Tan bellamente sin sentido.
Configurador

55
Simplemente lea la entrada vinculada en el rastreador de errores de PHP. En serio, wtf? oO La coherencia de Imho es un problema válido para cualquier API y simplemente responder con "usar un IDE decente entonces" simplemente no es una respuesta válida. Al menos podría haber sido redactado menos inflamatorio por los desarrolladores.
Baelnorn

2
Honestamente, ¡lo que me vuelve loco es que no debería ser una función en absoluto! Debería ser solo un método: $ haystack-> find ($ needle). Trato hecho.
Riwalk

19

Pitón

self parámetro en definiciones de métodos de instancia


En un método de clase, generalmente se llama cls y usar self va en contra de la convención.

Realmente tiene sentido si lo piensas. Es lo mismo que declarar un método privado en otros idiomas, el parámetro self es explícito en python, donde está implícito en otros idiomas. Si desea que sea implícito, agregue el decorador @classmethod antes de la declaración del método. Ver docs.python.org/library/functions.html#classmethod . Aprender los detalles de cómo funciona esto le dará una idea de cómo se hace implícitamente en otros idiomas.
Evan Plaice

44
Entiendo las razones y por qué se deja allí neopythonic.blogspot.com/2008/10/… pero todavía no me gusta
Goran Peroš

@Evan Plaice: 'el parámetro self es explícito en python donde está implícito en otros idiomas'. Eso es solo una parte de la historia. La otra parte es que Python se escribe semanalmente. Juntos es terrible, olvidarse selfes fácil y cuesta tiempo.
maaartinus

@maaartinus Luego agregue un decorador de método de clase a sus métodos de instancia. No tiene nada que ver con 'débilmente tipado'. Simplemente hace obvia la relación entre métodos / funciones estáticas (sin parámetro 'self') y métodos de instancia (incluye 'self'). Un método de instancia no conoce su clase padre a menos que le dé una referencia para hacerlo. En otros idiomas, la característica distintiva que describí está escondida detrás del azúcar sintáctico. Si tuviera la opción de hacerlo todo, habría comenzado a aprender OOP en Python primero.
Evan Plaice

18

Java

Período. Punto final. Fin de la historia.

¿Donde empezar? Oh, sé por dónde empezar: los genéricos increíblemente complicados, feos, estúpidos e inherentemente rotos de Java . ¿Necesito decir mas? :( bien Ok, entonces: Tipo de borrado .

Luego está la gestión de recursos no determinista. Kewl Piescher!

¿Qué sigue? Ah, sí: las expresiones estúpidas de Java son mi carne más irritante y bulliciosa. No puedo contar cuántas veces he sido manguera por no tener suficientes barras invertidas. Esto es incluso peor que no tener acceso a ninguna propiedad Unicode de este milenio, que es un toro completo. ¡¡¡Diez malditos años desactualizados !!! Completamente inutil. Basura que.

Luego está el error de que los atajos de clase de caracteres no funcionan en no ASCII. ¡Qué dolor real! Y ni siquiera consideres usar \p{javaWhiteSpace}; no hace lo correcto con varios puntos de código de espacio en blanco Unicode muy comunes.

¿Sabías que hay una \p{javaJavaIdentifierStart}propiedad? ¿En qué estado estaban pensando? Estoy tan contento de que hayan conseguido espías tan inteligentes trabajando duro.

¿Alguna vez intentó usar la bandera CANON_EQ? ¿Sabes que realmente lo hace, y lo que no? hace? ¿Qué tal el llamado "caso Unicode"? Un montón de cosas normales de la carcasa simplemente no funcionan en absoluto.

Luego hacen que sea difícil escribir expresiones regulares mantenibles. Java todavía no ha descubierto cómo escribir cadenas multilínea, por lo que terminas escribiendo cosas 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" 

¿Cuáles son todas esas líneas nuevas? Oh, solo estupidez de Java. Usaron comentarios de Perl, no comentarios de Java ( ¡idiotas! ) Que van hasta el final de la línea. Así que si no pones esos\n , cortarás el resto de tu patrón. ¡Duh y doble duh!

No uses expresiones regulares en Java: terminarás queriendo destrozar cosas, todo es tan doloroso y roto. No puedo creer que la gente aguante esto. Algunos no lo hacen .

Entonces podemos comenzar a hablar sobre las tonterías idiotas de Java con codificaciones. Primero, está el hecho de que la codificación de plataforma predeterminada siempre es una codificación poco convincente de 8 bits a pesar de que los caracteres de Java son Unicode. Luego está cómo no generan una excepción en un error de codificación. Te garantizamos que conseguirás basura. O qué tal esto:

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.

¿Cual es la diferencia? ¿Sabías que solo uno de ellos generará una excepción si tiene un error de codificación? El resto solo les hace bozal.

¡Luego está la idiotez de que los caracteres Java no son suficientes para contener un personaje! ¿Qué demonios están pensando? Por eso los llamo charchars. Debe escribir un código como este si espera que funcione correctamente:

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("."); }
    }
}

¿Y quién piensa hacer eso? Al lado de nadie.

¿En cuántos personajes hay "\uD83D\uDCA9"? ¿Uno o dos? Depende de cómo los cuentes. El motor de expresiones regulares, por supuesto, trata con caracteres lógicos, por lo que un patrón ^.$tendrá éxito y un patrón ^..$fallará. Esta locura se demuestra aquí:

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.

Esa idiotez es todo porque no puedes escribir lo perfectamente razonable \u1F4A9 , ni por supuesto recibes ninguna advertencia de que no puedes hacerlo. Simplemente hace lo incorrecto.

Stoooopid.

Mientras estamos en eso, toda la \uXXXXnotación es congénitamente muerte cerebral. El preprocesador de Java ( sí, me escuchaste ) lo hace antes de que lo haga Java, por lo que tienes prohibido escribir cosas perfectamente razonables como "\u0022", porque cuando Java lo ve, su preprocesador lo ha convertido """, por lo que pierdes. ¡Oh, espera, no si está en una expresión regular! Entonces puedes usarlo "\\u0022"bien.

Riiiiiiiight!

¿Sabías que no hay forma en Java para hacer una isatty(0)llamada? Ni siquiera se te permite pensar tales pensamientos. No sería bueno para ti.

Y luego está toda la abominación classpath.

¿O el hecho de que no hay forma de especificar la codificación de su archivo fuente Java en ese mismo archivo fuente para que no lo pierda? Una vez más, exijo saber: ¿QUÉ DEMONIOS PENSARON?

¡Para la locura! No puedo creer que la gente aguante esta basura. Es una broma completa. Prefiero ser un saludador de Walmart que sufrir las hondas y flechas de la indignante locura de Java. Todo está roto, y no solo no pueden arreglarlo, sino que no lo arreglarán.

Esto por las mismas personas astutas que se enorgullecían de un idioma que hacía ilegal tener una printf()función. Caramba, eso funcionó muy bien, ¿no?

Puros numbskulls. Abofetear es demasiado amable para ellos. Si quisiera programar en ensamblador, lo haría. Este no es un lenguaje rescatable. El emperador no tiene ropa.

Lo odiamos Lo odiamos por siempre . ¡Déjalo morir, morir, morir !


Jaja, bueno, no toco java porque está demasiado sin pulir como lo describiste. En cuanto a \ uD83D ... bueno, supongo que una mejor manera de decir esto es que preferiría que las cadenas no fueran UTF-16 sino UTF-32. Si acepta UTF-16-ness, entonces la expresión regular hace lo correcto; Es la llamada .length que se arruina.
Roman Starkov

44
-1. Con la excepción de los comentarios regexp y los escapes Unicode, ninguna de las cosas que mencionó es un elemento de sintaxis.
Jörg W Mittag el

3
@ Jörg, ¿quieres sintaxis? Ok, bien: Java te permite poner caracteres de control, incluidos ESC y NUL, en los identificadores. ¿Qué estaban pensando?
tchrist

44
@tchrist: ¡Guau! Si alguna vez escribo un programa Java de nuevo, todos mis variables tienen nombres que consiste en el número de caracteres de retroceso (variable ^H) :)
j_random_hacker

1
@tchrist, ¿te sientes mejor ahora?

16

Sintaxis de la declaración del puntero de función en C y C ++:

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

Eso declara un puntero de función llamado fcuyo puntero puede tomar dos intsy devolver un int.

Preferiría una sintaxis como esta:

f: (int, int) => int

Supongamos que desea declarar un puntero de función gcuyo puntero puede tomar dos intsy una función desde inty inthacia int, y devolver un int.

Con notación C o C ++, lo declararías como:

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

Con la notación propuesta anteriormente, se puede declarar lo mismo que:

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

Último es mucho más intuitivo IMO.


Aparte: el lenguaje de programación llamado OOC corrige esta sintaxis (y varios otros problemas sintácticos en C y C ++). Echa un vistazo a su página de inicio aquí .


De acuerdo, algunos "simples C" / "C ++" no lo admiten, o lo admiten con una sintaxis diferente. Una sintaxis especial, ayuda a indicar cuándo se admite una función de lenguaje de programación. Es por eso que C # agregó la sintaxis "delegado".
umlcat

Los delegados no solo son azúcar sintáctica porque también almacenan el objeto (al contrario de los punteros de función miembro de C ++, que tienen una sintaxis aún peor que los punteros de función regular)
Tamás Szelei

14

Verbosidad en Java.

es decir:

public static final int 

66
¿Comparado con? (15 caracteres)
TheLQ

77
En comparación con: const intpor ejemplo.
OscarRyz

11
"public static final int x = 4;" en comparación con "x = 4" en Haskell.
Jared Updike

24
Eso no es verbosidad. Intenta escribir a+(b*c)/d*e+f/g^20usando BigIntegerJava. ¿Por qué este lenguaje no permite la sobrecarga del operador?
MAK

44
@Michael: los programadores que necesitan protegerse de sí mismos a este costo pueden protegerse mejor (y reducir el dolor para todos los demás) al no programar en absoluto: D.
MAK

12

\ we \ wouldnt \ fix \ our \ parser sintaxis de espacio de nombres en PHP

La sintaxis no solo es fea, sino que genera confusión cuando los desarrolladores más nuevos tienen que pensar en los espacios de nombres en las cadenas. (PHP interpola barras invertidas en cadenas de comillas dobles como secuencias de escape. Intentar representar un espacio de nombres como \you\should\never\do\thaten una cadena de comillas dobles en lugar de una cadena de comillas simples conducirá a nuevas líneas, pestañas y desastres).


Sí, alguien pensó en una mejor :: forma de hacer esto, pero PHP insiste en que cada operador debe ser diferente. Sin embargo, tengo curiosidad por saber cuál es el problema del mal uso.
Alan Pearce

De acuerdo. PHP requiere espacios de nombres, pero esa sintaxis lo
arruina

9

Desprecio el hecho de que las llaves pueden ser opcionales después de una declaración if / while / for.

Especialmente cuando veo código como,

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

Por favor, solo ponga los frenos y termine con eso.


66
Hmm ... esto depende. Para "Abortar Ifs" que simplemente verifica una condición y devuelve un código de error (o arroja una excepción), prefiero no ver las llaves.
Billy ONeal

44
Estoy de acuerdo si se limita a casos extremos de varios niveles, pero su declaración es demasiado general. Hay una gran utilidad en la capacidad de tener formas cortas para ifs y bucles simples de una sola declaración.
Timwi

2
Mi regla: solo si una declaración requiere múltiples subenunciados o si contiene dicha declaración, debe estar entre llaves. Por for (...) while (...) if (...) { x(); y(); }lo tanto, es mejor reescribirlo for (...) { while (...) { if (...) { x(); y(); } } }, con sangría apropiada, por supuesto.
Jon Purdy

66
Soy todo lo contrario: desprecio a las personas que insisten en poner aparatos ortopédicos cuando son completamente innecesarios. Solo aprende a programar.
Jerry Coffin

3
Realmente me gustan los corchetes incluso en declaraciones if simples. Me hace seguir mejor el flujo de un programa.
Ricardo Santos

9

VBScript no tiene operadores lógicos

A diferencia de casi todos los lenguajes sensibles, VBScript usa operadores bit a bit en lugar de operadores lógicos. ¿Qué significa esto en la práctica? Bueno, como Eric Lippert señala :

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

y

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

NO son lo mismo en VBScript!

Sin embargo, lo que es peor, esto significa que no hay una evaluación de cortocircuito en VBScript, por lo que la siguiente declaración bloqueará su programa si BlahesNothing

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

Así es, ¡VBScript evaluará ambas partes de la comparación AND, incluso si la primera es falsa! Sólo deja que se hunda...


3
Hasta el día que has cazado un error dentro de un If x Then ... If Not x Then ... End If ... End Ify has descubierto que x es 2, realmente no has programado en VB / VBScript.
configurador

7

EDITAR: Después de la discusión en los comentarios, decidí actualizar esta respuesta para explicarme mejor.

Realmente odio el aspecto de los punteros de función en C. Por lo general, cualquier declaración de variable parece una tupla de: Por type varname; otro lado, las declaraciones de puntero de función se parecen a una declaración de la función con * antes del nombre de la función. Puedo aceptar esto como una descripción de un tipo de puntero, pero en C esto declara tanto el tipo como el nombre de una variable de ese tipo. Esto me parece inconsistente porque las declaraciones de tipo son distintas de las declaraciones de variables. struct myStruct{int X; int Y;}solo define un tipo, no define una variable llamada myStruct. Asimismo, no veo ninguna razón para que las declaraciones de tipo y las declaraciones de variables se agrupen en una declaración atómica en punteros de función, ni aprecio la desviación detype varname; estructura.

Alguien señaló que es consistente con alguna regla espiral, y ese puede ser el caso, pero la marca de una buena sintaxis es que se explica por sí misma y su lógica interna es obvia. La regla espiral no es obvia de ninguna manera.


1
Es coherente con el resto del lenguaje, por lo que ¿quizás su queja sea sobre la sintaxis de los declaradores de C en general? ¿Prefieres la sintaxis utilizada en Go ?
finnw

¿Consistente de qué manera? Por lo general, va: escriba varname; Y cuando creamos un nuevo tipo compuesto, como una estructura, primero viene la declaración, tal vez con un typedef, y luego creamos una variable de ese tipo. Cuando declaramos un puntero de función, es int (* foo) (int arg1, int arg2), que luego se usa como el tipo de argumento pasado a una función: void newFoo (int (* foo) (int arg1, int art2 )) .... y como una variable: foo = a_compatible_func; Creo que una declaración de función primero, y luego una declaración var después sería más consistente, así: typedef int (* foo) (int, int) MyFoo; MyFoo myfoo;
EpsilonVector

Por eso lo tienes typedef.
zneak

44
@EpsilonVector: tiendo a estar de acuerdo en que la sintaxis del puntero de función es desagradable, pero hay una regla simple a seguir que hace que sea más fácil de leer. La regla espiral en el sentido de las agujas del reloj (¿tal vez la has visto?): C-faq.com/decl/spiral.anderson.html
greyfade

1
EpsilonVector: no estoy seguro de qué esperaría de una declaración de variable de puntero para declarar que no sea el nombre de la variable.

6

Semicolones en VBScript - o la falta de ellos

Paso todo el día trabajando en idiomas que esperan punto y coma al final de cada línea. Agregue uno al final de la línea en VBScript y su código ya no se ejecutará.


44
votar esto, no porque me gusten especialmente los punto y coma, sino porque realmente odio la forma en que VB fomenta las líneas realmente largas al hacer que los saltos de línea sean tan inconvenientes.
Shog9

6

Argumentos de entrada / salida. Estoy a favor de los argumentos (bueno que soy), los argumentos también están bien, pero un argumento que debe transmitir estos dos estados me molesta.

Lo que apunto aquí son funciones que toman la entrada de un parámetro y luego sobrescriben esa entrada con alguna salida. Está bien pasar un objeto por referencia para actualizarlo. Pero, sobre todo para los tipos primitivos, tomar un objeto, usarlo y luego cambiarlo por completo, no es correcto para mí. No debe cambiar el significado del argumento a través de un inout.


¿Qué idioma tienes en mente? Si C #, no estaría de acuerdo con que es molesto porque siempre es explícito (a diferencia de C ++). Además, no conozco ningún lenguaje convencional en el que se ve obligado a declarar argumentos como in / out.
finnw

@finnw nunca he visto un lenguaje en el que tenías que decir inde inargumentos o bien, sólo estoy hablando de ellos. Además, en mi opinión, nada puede excusar un argumento de entrada / salida, y hacerlo explícito no alivia el dolor. No debería haber ninguna razón para tener que inicializar una variable local con un valor útil para la función, y tener esta misma variable y luego contener de repente lo que la función decidió poner allí. Estos dos deben ser distintos. Siempre.
zneak

Lo siento, no estaba muy claro allí. Quise decir "No sé de ningún idioma donde todos los argumentos estén implícitamente en + fuera", es decir, no está obligado a usar esa función, pero hay casos de uso legítimos (por ejemplo, actualizar un lugar structdonde el nuevo valor depende del valor de otro campo del mismo struct.)
finnw

@finnw Los objetos pasados ​​por referencia (como instancias de classobjetos en C #) que están siendo modificados por una función están bien para mí. Además de que no me gustan las estructuras no constantes, también está bien pasar un structcon la refpalabra clave para actualizarlo. Lo que realmente odio es cuando la entrada se sobrescribe con la salida. El mejor ejemplo que se me ocurre es la acceptfunción de socket de Berkeley : necesita un socklen_t*argumento que, en la entrada, debe contener el tamaño de lo struct sockaddr*que ha pasado; y en la salida, contendrá el número de bytes que se le han escrito. Esto debería ser criminal.
zneak

Estoy de acuerdo en que es malo (IIRC, algunas funciones de E / S de Win32 hacen lo mismo) pero eso es un mal uso de la función (la llamada a la función cambia el significado de la variable transferida, no solo su valor) y no significa la función en sí es malo
finnw

6

Declaraciones de matriz en C y C ++.

Típicamente, una declaración variable es del formato type variable_name. Puede leer fácilmente esas declaraciones de izquierda a derecha. Pero int foo[size]al principio parece que está declarando foocomo un int, y luego lees más y ves ese tipo de "conjunto de enteros". int[size] foolee mucho mejor.

Y también odio cuando los programadores declaran punteros como éste por una razón similar: int *foo. Por alguna razón que no he descubierto, esa es la forma típica en que está escrito.


1
Re declaraciones de puntero: se escriben así porque el ' ' se une al nombre de la variable, no al tipo. Entonces int* a, b;* no declara ay bcomo punteros; solo aes. Por lo tanto, es mejor escribirlo como int *a, b;(o incluso mejor escribirlo como dos declaraciones).
Steve Melnikoff

Buen punto. Es una pena *que no se una al tipo.
Jacob

2
¿Y esto no quiere decir nada de punteros de función ... void(int) *f;? No:void (*f)(int);
Nota personal - piense en un nombre

En C ++ moderno hay muy poca necesidad de punteros y matrices.
fredoverflow

2
@Steve Melnikoff: Aunque hice +1 en esta respuesta, creo que el int* a, b;tema que mencionaste es mucho más atroz.
j_random_hacker

5

Parametrización redundante en Java:

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

¿Qué otro tipo de parametrización cree que foo podría tener el compilador ?


44
Espero que esté al tanto de la inferencia de tipos (limitada) de Java? HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
finnw

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

55
Bueno, puede tener cualquier tipo que desee, los tipos se borran de todos modos ...
configurador

¿Falta de inferencia de tipos, quieres decir?
missingfaktor

What other type parameterization does the compiler think foo could have?- Por alguna razón, considera que es de tipo sin formato, como si alguien en su sano juicio pudiera incluso mezclar tipos sin formato y parametrizados.
maaartinus

5

Como la gente ya se ha quejado de =vs. ==, permítanme señalar una alternativa mucho peor. PL / Tenía ambas :=y =, pero cuando algo era "obviamente" una tarea, te permitía salirte con la tuya =para hacerlo. Utilizando:= permite forzar que algo sea una tarea en una situación en la que el compilador lo interpretaría como una comparación.

Desafortunadamente, el compilador no siempre decidió las cosas de la manera que cabría esperar. Considere solo un ejemplo obvio:

A = B = 0;

Ahora, para la mayoría de las personas familiarizadas con la mayoría de los lenguajes "ordinarios", el significado de esto es bastante obvio: asignar 0 a A y B. PL / I es solo un poco ... diferente. Por razones conocidas solo por los diseñadores (locos) del lenguaje, el primero =se interpreta como una tarea, pero el segundo= se interpreta como una comparación. Por lo tanto, esto compara B con 0, y luego asigna el resultado de esa comparación a A (siguiendo la convención de estilo C que "falso" da como resultado 0 y "verdadero" en 1).

Entonces, si B era 0, entonces A se convierte en 1. De lo contrario, A se convierte en 0. En otras palabras, en lugar de asignar el mismo valor a A y B, esto realmente garantiza que A no pueda tener el mismo valor que B.

En pocas palabras: aunque el estilo C / C ++ / PHP inicialmente parece un problema, la alternativa es mucho peor 1 .

1 Bueno, técnicamente, hay otra alternativa: el estilo Pascal, donde =siempre significa que la comparación y la asignación siempre requieren :=. Después de usar eso por un tiempo, es bastante obvio (al menos para mí) que la asignación es bastante más común que la comparación que si va a requerir "cosas" adicionales para desambiguar a los dos, definitivamente debe mantener las tareas limpias y simples y requieren el "grunge" adicional en las comparaciones, no al revés.


1
Incluso propondría usar ==para igualdad y :=para asignación. De esta manera, tiene más para escribir, pero evitar las solitarias =ayuda a evitar errores.
maaartinus

@maartinus: al menos para mí, eso parece la peor posibilidad absoluta, pero así es la vida ...
Jerry Coffin

3

Perl

  1. Deseo que Perl me deje escribir if($x < 10) do_something();. Por el momento, tienes que escribir eso como do_something() if($x < 10);o como if($x < 10) { do_something(); }.

99
do_something() if ($x < 10);no es tan malo
zneak

No lo es, y en muchos casos es mucho más limpio que if(..) ...arrancar, ya que puede hacer que todas las expresiones se alineen a la derecha. Pero hay momentos que realmente quiero decir if($x < 10) do_something();, y es lamentable que Perl no me deje.
Gaurav

77
Es lamentable hasta que escribe if ($x<10) do_something(); and_call_me(); y luego se pregunta por qué nunca recibe una llamada. Desearía que C y la familia requirieran las llaves, para evitar ese tipo de error.
AShelly

2
@ AShelly: o por qué siempre recibes una llamada, en realidad.
zneak

1
@zneak Excepto no elses. (Desearía que tuviera EXPR1 if COND else EXPR2como Python)
Ming-Tang

3

reinterpret_cast<unsigned long>en c ++. Esta operación es útil para tratar con API extranjeras y garantizar la precisión numérica, ¿por qué debería ser tan difícil de escribir y tan feo de ver?


17
Es feo recordarle que debe esforzarse por escribir código que no lo requiera. :)
greyfade

Para mí, ese es un buen argumento teórico de la informática, pero en mi experiencia, es demasiado útil para evitarlo (Sin embargo, gran parte de mi experiencia es simplemente la vieja C, por lo que probablemente tenga un sesgo).
AShelly

55
No es realmente un argumento teórico de CS: el uso de a reinterpret_casten C ++ es un olor a código muy fuerte. El 99% de las veces, cuando está a punto de usarlo, es probable que no necesite hacerlo, probablemente haya hecho algo mal. El otro 1% de las veces, estás interactuando con C. reinterpret_castrompe el sistema de tipos para hacer que algo funcione cuando de lo contrario no puede. Eso suele ser algo malo.
greyfade

3

La construcción for ... in en JavaScript y la construcción foreach en PHP cuando se repite en matrices. Ambos hacen que sea más fácil escribir errores que el código correcto.


3
Wow, eso es una mierda. "Que el código correcto". Vete.
Jonathan Sterling el

Si tengo que escribir código adicional para usarlos de manera segura, es más fácil usarlos incorrectamente en mi libro. For ... in requiere comprobaciones adicionales para asegurarse de que no está iterando sobre objetos del prototipo, y foreach requiere que limpie las referencias después o corra el riesgo de sobrescribir el último valor en la matriz.
Joeri Sebrechts

el foreach con referencias cambiantes (y operador) es un error famoso ...
umlcat

1
Estoy confundido, pensé que era de conocimiento común que la construcción "for..in" en javascript está rota ... ¿por qué es ofensivo?
lvilnis

2

Punteros de matrices o matrices de punteros en C / C ++. Todavía estoy confundido acerca de estos.


3
Lee el tipo al revés. int[]*es un puntero a una matriz de enteros y int*[]es una matriz de punteros a enteros. Funciona bien con consts también: int* constes un puntero constante a números enteros, mientras que const int*y int const*son punteros a enteros constantes (o en las constantes enteras).
zneak

@zneak: "De derecha a izquierda" no funciona, vea la regla mencionada "espiral en sentido horario" / "al revés" .

O simplemente use typedefs y no habrá confusión.
Billy ONeal

En C ++ moderno hay muy poca necesidad de punteros y matrices.
fredoverflow

44
@tchrist: No es cierto. int (*p)[10];declara pser un puntero a una matriz de 10 ints. Si sizeof (int) == 4, entonces p++avanzará ppor 40.
j_random_hacker


1

Javascript / Java, etc., es igual a la comparación, por ejemplo, if (a == 1)

¿Cuántas veces escribo si (a = 1)?

Como humano, lo leí perfectamente. Pero el maldito intérprete / compilador dice: "hey, asignaré 1 a a, luego comprobaré si a es igual a 1, ¡y creerías que sí!

Me lleva por la pared.

si (a == 1) es mucho menos legible, y el intérprete / compilador debería saber lo que quiero decir de todos modos; muchos otros lenguajes menores (VB) han estado funcionando con éxito durante cientos de años.


¿Qué se if (a = true)supone que significa?
Tom Hawtin - tackline

2
La asignación simplemente no debería devolver un valor. A veces es útil, pero en la mayoría de los casos es solo un dolor en el cuello.
configurador

en Javascript, JSLint lo atrapará por usted.
Zachary K

El problema es que la asignación en condiciones puede ser útil. Encuentro <tt> while (element = list-> next ()) </tt> bastante legible. Por lo tanto, no estoy seguro de que me gustaría eliminarlo.
Inca

3
@Tom: Significa que no entiendes los booleanos. Si querías decir if (a == true), solo escribe if (a). Si quiso decir a = true, entonces la ifdeclaración es redundante.
dan04


0

structPointer->memberen C / C ++. Puede ser bueno para leer el código de otra persona, pero no me gusta. Dos personajes en lugar de uno ... ¡qué desperdicio de espacio!


2
Desafortunadamente, debe distinguirse de lo .que se aplica a los miembros de un objeto sin puntero. La sintaxis ambigua es mala, mmmkay?
greyfade

2
@greyfade: ¡Sí! Debido a que el compilador no puede usar sus reglas de sistema de tipos para saber cuándo está usando un tipo puntero a estructura y aplicar la desreferencia implícitamente. ¡No, eso es una locura! (Y sin embargo, de alguna manera puede darte un mensaje de error cuando te equivocas). La sintaxis no tiene nada de ambiguo. Es solo que C es un desastre mental, como siempre. Delphi hace desreferencias implícitas bien, si usted está trabajando realmente en los rincones oscuros que requieren punteros a los registros, lo que sin duda se puede hacer sin confundir un analizador ...
Mason Wheeler

55
@Mason: ¿Qué pasa con casos como shared_ptr, donde ->accede al tipo contenido y .accede a las propiedades de shared_ptrsí mismo? Lo siento, pero estoy completamente en desacuerdo aquí.
Billy ONeal

2
podría ser peor. Podría ser PHP, donde debe usar ->para acceder a miembros de cualquier cosa .
Carson Myers, el

1
@maaartinus: Cualquier código que se base en gran medida en un orden no obvio de operaciones no es un código que escribiré.
Billy ONeal

0

Código Scala multilínea entre paréntesis

Por ejemplo:

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

Lo que realmente obtienes de él es excelente. Genera el constructor y los captadores y establecedores para usted. Pero seguro que es feo y rompe todos mis modelos mentales sobre cómo sangrar código y básicamente me hace sentir como si estuviera en una especie de sándwich extraño con Java a un lado y Lisp al otro. (Oh, espera ... ese es más bien el punto de Scala).


Estoy confundido: ¿te refieres a la porción entre paréntesis ( val bary así sucesivamente) o la porción entre llaves (la siguiente parte extends Model)? (No hay paréntesis en ese código)
Billy ONeal

3
La porción entre paréntesis. Soy Inglés. Nos referimos a esos como paréntesis, maldita sea, porque en esa situación no están cumpliendo un papel entre paréntesis.
Tom Morris

2
No se ve tan mal si se sangra de esta manera: pastebin.com/h9qC8XGg
missingfaktor

Me resulta más legible escribir estas listas de parámetros de constructor horizontalmente, especialmente cuando solo tengo unos pocos parámetros.
MJP

A mí me parece un método. Como Simula Buena vieja escuela
Tom Hawtin - tackline
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.