Característica más extraña del lenguaje

974

¿Cuál es, en su opinión, la característica de lenguaje más sorprendente, extraña, extraña o realmente "WTF" que ha encontrado?

Por favor, solo una función por respuesta.

Robert Harvey
fuente
55
@gablin Creo que si combinara delimitadores LISP con expresiones regulares PERL utilizando el análisis de JavaScript, cubriría el 90% del WTF ...
Talvi Watia

Respuestas:

1859

En C, las matrices se pueden indexar así:

a[10]

Lo cual es muy común.

Sin embargo, la forma menos conocida (¡que realmente funciona!) Es:

10[a]

lo que significa lo mismo que el anterior.

Edan Maor
fuente
758
eso es porque un [10] significa * (a + 10) ... y 10 [a] significa * (10 + a) :)
Michel Gokan
77
No olvides "Hola Mundo" [i]. O yo ["Hello World"]
Richard Pennington
167
O, más útil, "0123456789abcdef" [x y 0xf]
Varilla de nivel
17
@frunsi: Siempre funciona como se esperaba. La suma de punteros no es lo mismo que la suma de enteros simples en las direcciones. Es conmutativo, sin importar el tamaño del tipo en cuestión.
R. Martinho Fernandes
12
@mcv: a [10] es lo mismo que "* (a + 10)", donde la expresión "a + 10" es aritmética de puntero (y como a es un corto, en su ejemplo, a + 10 significa 'comenzar en dirección de a, y mover 10 cortos, es decir, 20 bytes '). La expresión 10 [a] se interpreta como "* (10 + a)", donde "10 + a" también es aritmética de puntero y se trata exactamente de la misma manera.
Edan Maor
1292

En JavaScript:

 '5' + 3 gives '53'

Mientras

 '5' - 3 gives 2
Dipstick
fuente
81
Recuerdo cuando comencé a usar JavaScript usando este tipo de técnica para agregar números en cadenas: "111" - - "222" da 333 mientras que "111" + "222" da "111222".
Callum Rogers
112
+para la concatenación de cuerdas es horrible
Matteo Riva
416
+ para concat no es el problema. Mecanografía débil es.
FogleBird
270
@FogleBird Ninguno de los dos es realmente el problema. Es solo la combinación de los dos con reglas de coerción inconsistentes.
TM.
70
Básicamente, + es concat cuando hay una cadena involucrada. ¿Por qué no pueden codificar algo como '123456' - 456 = '123'? Eso puede ser interesante.
Jimmie Lin
872

En JavaScript, la siguiente construcción

return
{
    id : 1234,
    title : 'Tony the Pony'
};

retornosundefined es un error de sintaxis debido a la inserción punto y coma implícita disimulado en la nueva línea después return. Sin embargo, lo siguiente funciona como es de esperar:

return {
    id : 1234,
    title : 'Tony the Pony'
};

Peor aún, este también funciona (al menos en Chrome):

return /*
*/{
    id : 1234,
    title : 'Tony the Pony'
};

Aquí hay una variante del mismo problema que no produce un error de sintaxis, simplemente falla en silencio:

return
    2 + 2;
DrJokepu
fuente
225
La inserción de punto y coma es una de las partes más malvadas de JavaScript.
230
Siempre tiene problemas cuando diseña funciones de lenguaje en el supuesto de que sus usuarios serán en su mayoría idiotas.
Rob Van Dam
8
De hecho, tuve ese problema, al ser desarrollador de C #, puse la llave en una nueva línea. Me tomó horas darme cuenta de cuál era el problema. ¡Incluso cuando resolví el problema, no supe cuál era el problema hasta que leí tu respuesta!
Fedor Hajdu
24
Nick Retallack: Debido a que, debido a la sintaxis de punto y coma y comillas tipo R de JavaScript, no es evidente en absoluto que las nuevas líneas sean significativas.
Tamas Czinege
19
Si se supone que no debe usar el estilo C al programar en JavaScript, entonces fue bastante perverso de los diseñadores del lenguaje JavaScript elegir una sintaxis de estilo C.
Ryan Lundy
795

Tabla de verdad de JavaScript:

''        ==   '0'           // false
0         ==   ''            // true
0         ==   '0'           // true
false     ==   'false'       // false
false     ==   '0'           // true
false     ==   undefined     // false
false     ==   null          // false
null      ==   undefined     // true
" \t\r\n" ==   0             // true

Fuente: Doug Crockford

Chandra Patni
fuente
237
Lo bueno es que Javascript tiene el operador ===, entonces.
Anónimo el
65
Entonces, ¿para qué ==sirve a los ojos del diseñador de idiomas?
Chris S
137
Gente confusa
Javier
123
Sería bueno ==tener el significado de ===, y luego había otro operador, algo así ~=permitía la coerción de tipo.
TM.
18
@Otto En realidad, dado que nos estamos escapando, su ejemplo muestra que == no es simétrico. Por el momento, no he visto cómo se especificaría la conmutatividad para una relación binaria.
PeterAllenWebb
660

Trígrafos en C y C ++.

int main() {
   printf("LOL??!");
}

Esto se imprimirá LOL|porque el trigrafo ??!se convierte a |.

Andreas Bonini
fuente
71
¡Rápido! ¡Cuéntales a todos los programadores de C / b!
Esteban Küber
235
Los trigraphs son increíbles, porque puedes estar seguro de que nadie, nunca, sabrá qué. significará de Google sin saber el nombre ya.
zaratustra
56
Los trígrafos están deshabilitados por defecto en GCC.
Sastanin
360
Estos le permiten usar el "operador WTF": (foo ()! = ERROR) ??! ??! cerr << "Se produjo un error" << endl;
user168715
57
Los trigrafos eran un mal necesario cuando se introdujeron. Algunas plataformas simplemente no incluían ciertos caracteres clave para el lenguaje, por lo que se trataba de "trigrafos" o "no se puede tener un compilador de C período-fin-de-declaración, así que use el ensamblador". Consulte la descripción de Stroustrup en "El lenguaje de programación C ++".
Euro Micelli
573

Diversión con el boxeo automático y el caché de enteros en Java:

Integer foo = 1000;
Integer bar = 1000;

foo <= bar; // true
foo >= bar; // true
foo == bar; // false

//However, if the values of foo and bar are between 127 and -128 (inclusive)
//the behaviour changes:

Integer foo = 42;
Integer bar = 42;

foo <= bar; // true
foo >= bar; // true
foo == bar; // true

Explicación

Un vistazo rápido al código fuente de Java mostrará lo siguiente:

/**
 * Returns a <tt>Integer</tt> instance representing the specified
 * <tt>int</tt> value.
 * If a new <tt>Integer</tt> instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Integer(int)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * @param  i an <code>int</code> value.
 * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    if (i >= -128 && i <= IntegerCache.high)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

Nota: el valor IntegerCache.high predeterminado es a 127menos que lo establezca una propiedad.

Lo que sucede con el auto boxing es que tanto foo como bar el mismo objeto entero recuperado de la memoria caché a menos que se cree explícitamente: por ejemplo foo = new Integer(42), al comparar la igualdad de referencia, serán verdaderas en lugar de falsas. La forma correcta de comparar el valor entero es usar.equals;

yx.
fuente
31
Me tomó un par de segundos para ver por qué ... Java debe mantener un conjunto de instancias de Integer para valores entre -128 y 128, de lo contrario, asigna un nuevo Integer, ¿verdad?
Mike Akers
18
sin embargo, tenga en cuenta que si especifica un nuevo número entero (42) no utilizará la instancia del grupo, por lo que foo == bar se evaluará como falso
z -
10
Si es posible, siempre uso ints en lugar de Integers, pero si tuviera que usar Integers por alguna razón, ¿debería usar .equals () en lugar de ==?
MatrixFrog
246
Estoy tan contento de ser un programador de C #.
87
@Will: C # tiene algunas trampas muy similares. Ver blogs.msdn.com/jmstall/archive/2005/03/06/386064.aspx
spookylukey
373

Citando a Neil Fraser (mira al final de esa página),

try {
    return true;
} finally {
    return false;
}

(en Java, pero el comportamiento es aparentemente el mismo en JavaScript y Python). El resultado se deja como ejercicio para el lector.

EDITADO: Mientras estemos en el tema, considere también esto:

try {
    throw new AssertionError();
} finally {
    return false;
}
lorenzog
fuente
42
+1. Por alguna razón, me parece hilarante y no puedo dejar de reír.
outis
153
Afortunadamente, C # no permite tanta locura ...Control cannot leave the body of a finally clause
Richard Ev
64
Esto vuelve, falso, ¿verdad? Puede parecer un WTF (y posiblemente sea uno), pero vivo según la regla: finalmente siempre gana, a menos que bloquee la máquina antes.
Michael Stum
28
Para ser justos, culpo a la agradable explicación de TDWTF de recordar que finalmente siempre gana a menos que tire del cable de alimentación: thedailywtf.com/Articles/My-Tales.aspx
Michael Stum
22
No estoy seguro de qué debería devolver el código en este caso. Pero estoy absolutamente seguro de que no se debe poner returnen la finallycláusula.
jfs
325

APL (aparte de TODO), la capacidad de escribir cualquier programa en una sola línea.

Ej . Juego de la vida de Conway en una línea en APL :

texto alternativo http://catpad.net/michael/APLLife.gif

Si esa línea no es WTF, ¡entonces nada lo es!

Y aqui hay un video

lkessler
fuente
19
Amo el APL. ¡Ah, las alegrías de pasar una tarde entera escribiendo media línea de código! Lo primero que haré cuando obtenga un teclado donde pueda programar qué letras se muestran es volver a familiarizarme con APL.
Daniel C. Sobral
24
Parece un idioma para los griegos.
Esko
45
@Erik: Hay alegría de escribir código que se trata únicamente de lo que quieres y no de cómo llegar allí. De expresar su código como una sola expresión. Es como el último corte de katana perfecto. Por supuesto, en una pelea real preferiría tener un arma.
Daniel C. Sobral
77
@Daniel: Pasas una tarde entera para escribir una línea de código ... y una semana entera para leer una línea de código. ;-)
Jürgen A. Erhard
93
APL sería increíble de ver en una película de acción de ciencia ficción. Me imagino a alguien sentado en un terminal de tres colores murmurando "Cambie la forma del vector de misiles enemigos ... transponga ... logaritmo pi veces ... ¡suba de nivel y ejecute!" seguido de explosiones y vítores.
Joey Adams
321

Las cosas extrañas para las plantillas C ++ se pueden usar, lo que se demuestra mejor con "Literales analógicos multidimensionales" que usan plantillas para calcular el área de formas "dibujadas". El siguiente código es válido en C ++ para un rectángulo de 3x3

#include"analogliterals.hpp"
using namespace analog_literals::symbols;

          unsigned int c = ( o-----o
                             |     !
                             !     !
                             !     !
                             o-----o ).area;

O, otro ejemplo con un cubo 3D:

  assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );
josefx
fuente
18
Si bien los literales analógicos de Eelis son geniales, ¿son una característica extraña del lenguaje , o simplemente una forma extraña de usar una característica?
85
El verdadero WTF será el error del compilador generado por uno de los que está mal formado.
Andrew McGregor
66
Qué enfermo es eso ... despertarme nuevamente cuando hay una versión de AnalogLiterals que admite girar el literal alrededor del eje X, Y y Z en Eclipse ... ahora eso le daría a la "programación visual" un nuevo significado real.
TheBlastOne
2
¿Importa el orden de las o y las L y |?
Ming-Tang
44
El orden es importante, ya que las plantillas hacen un uso creativo de la sobrecarga del operador. (No haga esto con código real, el mal uso de los operadores hace que el código sea difícil de leer)
josefx
292

Las muchas variables incorporadas de Perl:

  • $#- No es un comentario!
  • $0, $$y $?- al igual que las variables de shell con el mismo nombre
  • , $&y $'- variables de coincidencia extrañas
  • $"y $,- variables extrañas para separadores de campo de lista y salida
  • $!- errnocomo un número pero strerror(errno)como una cadena
  • $_- la variable sigilo, siempre utilizada y nunca vista
  • $#_ - número de índice del último argumento de subrutina ... tal vez
  • @_ - los (no) nombres de la función actual ... tal vez
  • $@ - la última excepción planteada
  • %:: - la tabla de símbolos
  • $:, $^, $~, $-, Y $=- algo que ver con los formatos de salida
  • $.y $%- número de línea de entrada, número de página de salida
  • $/y $\- separadores de registros de entrada y salida
  • $| - controlador de buffer de salida
  • $[- cambie su base de matriz de 0 a 1 a 42: ¡WHEEE!
  • $}- Nada en absoluto, ¡curiosamente!
  • $<, $>, $(, $)- UID y GID reales y efectivos
  • @ISA - nombres de las superclases directas del paquete actual
  • $^T - tiempo de inicio del script en segundos de época
  • $^O - nombre del sistema operativo actual
  • $^V - ¿Qué versión de Perl es esta?

Hay mucho más de donde vinieron esos. Lea la lista completa aquí .

Chris S
fuente
83
La $[variable es la más malvada de todas.
Brad Gilbert el
24
Definitivamente lo agradecería si Perl 6 fuera algo que pudiera codificar sin tener que verificar perldoc perlvarcada cinco segundos. (Aunque confieso que la mitad del tiempo lo reviso pensando "Sé que hay una variable especial que puede hacer esto por mí, simplemente no recuerdo cuál ..." = P)
Chris Lutz
17
El problema use English;es que afecta el rendimiento de RegExp. No estoy inventando esto. perldoc.perl.org/English.html#PERFORMANCE
Dave Webb
13
@Dave: no es un problema debido a la opción -no_match_vars en la página que ha vinculado. @Brad: $ [es TAN malvado. La intención detrás de esto es malvada, sí, ¡pero tampoco funciona! @Artem: from perlvar "Los identificadores de Perl que comienzan con dígitos, caracteres de control o signos de puntuación están exentos de los efectos de la declaración del paquete y siempre están obligados a estar en el paquete principal; también están exentos de errores estrictos 'vars'". Entonces eso significa que @ $ se crearía y se asignaría sin error incluso bajo restricción. Ugh!
rjh
44
@Brian: ¿Cómo propones aprender la sintaxis cuando la documentación oficial en sí misma establece que hay circunstancias en las que el intérprete de Perl adivina heurísticamente lo que significa una secuencia de caracteres? Por ejemplo /$foo[bar]/, en , ¿es la [bar]parte una clase de caracteres o un subíndice de la matriz @foo? Grep perldata por la aterradora respuesta.
j_random_hacker
289

Manejo de PHP de valores numéricos en cadenas . Vea esta respuesta anterior a una pregunta diferente para obtener detalles completos pero, en resumen:

"01a4" != "001a4"

Si tiene dos cadenas que contienen un número diferente de caracteres, no pueden considerarse iguales. Los ceros a la izquierda son importantes porque son cadenas y no números.

"01e4" == "001e4"

PHP no le gustan las cadenas. Está buscando cualquier excusa que pueda encontrar para tratar sus valores como números. Cambie ligeramente los caracteres hexadecimales en esas cadenas y de repente PHP decide que ya no son cadenas, son números en notación científica (a PHP no le importa que use comillas) y son equivalentes porque los ceros iniciales se ignoran para los números. Para reforzar este punto, encontrará que PHP también se evalúa "01e4" == "10000"como verdadero porque estos son números con valores equivalentes. Este es un comportamiento documentado, simplemente no es muy sensato.

Dan Dyer
fuente
56
Solo usa === y! ==. Que debe usarse de todos modos, a menos que se necesite una comparación de tipos sueltos.
Dykam
14
@Dykam, si sigues el enlace a la respuesta completa, verás que he abordado el uso del operador ===.
Dan Dyer
18
¡Golpes débiles de mecanografía nuevamente!
gillonba
43
Siempre supe que PHP era un pecado. Hasta ahora no me daba cuenta de que era un pecado imperdonable: D
Thomas Eding
2
Deben usar personas tecnológicas para usar === en cualquier libro de programación o tutorial. Nota agregada: en una aplicación PHP mal escrita pude proporcionar como contraseña todo lo que se analizó como el mismo número.
Pepijn
282

Vamos a votar por todos los idiomas (como PL / I) que intentaron eliminar las palabras reservadas.

¿Dónde más podrías escribir legalmente expresiones tan divertidas como:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

( IF, THEN, ELSESon nombres de variables)

o

IF IF THEN THEN ELSE ELSE

( IFes una variable THENy ELSEson subrutinas)

MZB
fuente
1
@quark: esa es una respuesta separada a esto! ;) ... (y sí, puede programar con inglés, simplemente impleméntelo como .ppt para otros desarrolladores.;)
Macke
28
@RoadieRich un grupo de búfalos no es explícitamente de Buffalo, son búfalos indescriptibles.
Jürgen A. Erhard
18
John, donde James había tenido, había tenido, había tenido, había tenido un mejor efecto en el maestro.
GameFreak
44
El otro día vi algunos fabricantes de letreros afuera de una fábrica de helados Ben and Jerrys. Critiqué su trabajo, les dije que no había suficiente espacio entre ben y and y and y jerrys.
Tom Gullen
99
Tal vez sea necesario para futuros programas temporales. SI ENTONCES = AHORA && DONDE = AQUÍ ENTONCES CUANDO = LUEGO AHORA MÁS = EN OTRA PARTE
Kelly S. French
282

Es bueno conocer la 'característica' de conversión octal de JavaScript:

parseInt('06') // 6
parseInt('07') // 7
parseInt('08') // 0
parseInt('09') // 0
parseInt('10') // 10

Más detalles aquí .

Brian Deterling
fuente
6060
¡Me quedé atrapado en un error que todos los números funcionaron excepto 8 y 9! Se estaba volviendo loco! Gracias Brian!
Faruz
10
@Yada ¿No te refieres a octal? Hexadecimal es 0x.
luiscubal
48
Y es por eso que parseInt toma un argumento adicional (opcional) :).
LiraNuna
10
el 0 inicial significa número octal. como 8 no es un dígito octal válido, el resultado debe ser 0.
devio
22
... y parseInt ('010') -> 8 solo para confundirte.
Richard Gadsden
213

El dispositivo de Duff en C!

En C uno puede entrelazar un do / while con una instrucción switch. Aquí un ejemplo de una memcpy usando este método:

void duff_memcpy( char* to, char* from, size_t count ) {
    size_t n = (count+7)/8;
    switch( count%8 ) {
    case 0: do{ *to++ = *from++;
    case 7:     *to++ = *from++;
    case 6:     *to++ = *from++;
    case 5:     *to++ = *from++;
    case 4:     *to++ = *from++;
    case 3:     *to++ = *from++;
    case 2:     *to++ = *from++;
    case 1:     *to++ = *from++;
            }while(--n>0);
    }
}
Frunsi
fuente
99
El dispositivo de Duff es probablemente una buena razón para que la declaración de cambio no tenga una interrupción por defecto ;-) Sin embargo, todavía no vi ningún otro buen uso del interruptor y el bucle entrelazados, pero probablemente haya uno. Oh, espera, sí, hay otro uso: corutinas y prototipos.
Frunsi
16
@frunsi: "El dispositivo de Duff es probablemente una buena razón para que la declaración de cambio no tenga una interrupción por defecto" - Siempre haga que el caso común sea el predeterminado. No diría exactamente que este es el caso común ...
BlueRaja - Danny Pflughoeft
66
@mcv probablemente sea más fácil si intenta leerlo como código de ensamblaje, es decir, whileal final es un (condicional) de JMPregreso al do, lo que explica por qué puede omitirlo doy aún terminar en el bucle.
wds
14
Tenga en cuenta que el dispositivo de Duff generalmente produce un código PEOR que la declaración de bucle normal para los compiladores modernos, que saben cómo (mejor) desenrollar el bucle de lo que puede hacer a mano.
Billy ONeal
37
@frunsi: Duff mismo, al publicarlo, afirmó algo como esto: "Esto definitivamente proporciona un argumento en la discusión sobre si el cambio debería fallar por defecto, pero no estoy seguro de si el argumento es a favor o en contra".
SF.
204

Algol pasa por nombre (ilustrado usando la sintaxis C):

int a[3] = { 1, 2, 3 };
int i = 1;

void f(int j)
{
    int k;
    k = j;  // k = 2
    i = 0;
    k = j;  // k = 1 (!?!)    
}

int main()
{
    f(a[i]);
}
Richard Pennington
fuente
33
Si lo piensas, en realidad tiene algún tipo de sentido retorcido
RCIX el
90
Este es el último "pase por referencia".
Dykam
3
Sin embargo, es posible en Scala ( def f(j : => int))
Dario
10
¿Entonces esto es algo así ... template<typename T> struct by_name { virtual operator T&() = 0; }; void f(by_name<int> j) { ... } int main() { f(struct : by_name<int> { operator int&() { return a[i]; } }); }?
Simon Buchan
2
En realidad es bastante sencillo: genera un pequeño fragmento de código (generalmente llamado "thunk", de ahí mi juego de palabras anterior) que calcula la dirección resultante de la expresión, en este caso & a [i]. Se pasa un puntero a esta función a la función llamada, que luego la usa para calcular la dirección actual cada vez que se accede al parámetro.
Richard Pennington el
189

En Python:

>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False

No es un WTF, sino una característica útil.

MAK
fuente
176
Ojalá todos los demás idiomas tengan esta característica
vava
32
Al igual que con casi todas las características interesantes de Python, parece que Guido acaba de ALGOLIZAR la sintaxis de una característica genial de Lisp. :-)
Ken
44
Geoffrey, es una característica, y (10 > 5 > 1) != ((10 > 5) > 1)en Python.
sastanin
18
Además, evalúa solo una vez, por lo que (funct_a(5)+5 > b > funct_a(5))solo llama funct_a(5)una vez. ¡Es una GRAN característica!
Khelben
57
@Khelben: No, funct_ase llamará dos veces en ese ejemplo. Sin b > funct_a(5) > cembargo, solo se llamará una vez, a diferencia de b > funct_a(5) and funct_a(5) > c.
Baffe Boyois
189

En Java:

int[] numbers() {
  return null;
}

Se puede escribir como:

int numbers() [] {
  return null;
}
Chandra Patni
fuente
23
¡Guauu! ¡Ojalá pudiera ser una mosca en la pared cuando se diseñó esa sintaxis de matriz!
Adam Paynter el
29
Odio decir esto, pero el WTF es una extensión consistente del sistema de tipo C. Si se permitiera a las funciones de C devolver matrices, así sería. El más agradable es una violación de consistencia para hacerlo más legible. Al igual que "const char * var" vs "char const * var".
Gordon Wrigley
15
@ Adam - En realidad, tiene sentido cuando consideras que la declaración de variable permite de manera similar tanto "int stuff []" como "int [] stuff". Simplemente dejan que las mismas reglas funcionen para la declaración del método.
Brandon Yarbrough
2
@lImbus: En realidad, const T*y T const*son equivalentes, es lo T* constque contrasta el puntero. Además, odio sin fuentes.
Simon Buchan
3
Después de todo, numbers()[2]es una declaración legal.
badp
184

INTERCAL es probablemente el mejor compendio de características de lenguaje más extrañas. Mi favorito personal es la declaración COMEFROM que es (casi) lo opuesto a GOTO.

COMEFROM es aproximadamente lo opuesto a GOTO en que puede llevar el estado de ejecución desde cualquier punto arbitrario del código a una declaración COMEFROM. El punto en el código donde ocurre la transferencia de estado generalmente se da como un parámetro para COMEFROM. Si la transferencia se realiza antes o después de la instrucción en el punto de transferencia especificado depende del idioma utilizado. Dependiendo del lenguaje utilizado, varios COMEFROM que hacen referencia al mismo punto de partida pueden ser inválidos, no deterministas, ejecutarse en algún tipo de prioridad definida, o incluso inducir una ejecución paralela o concurrente de otro modo como se ve en la Intercal roscada. Un ejemplo simple de una declaración "COMEFROM x" es una etiqueta x (que no necesita estar físicamente ubicada cerca de su correspondiente COMEFROM) que actúa como una "puerta trampa". Cuando la ejecución del código alcanza la etiqueta, el control se pasa a la instrucción que sigue al COMEFROM. El efecto de esto es principalmente hacer que la depuración (y la comprensión del flujo de control del programa) sea extremadamente difícil, ya que no hay indicación cerca de la etiqueta de que el control saltará misteriosamente a otro punto del programa.

Jeff Foster
fuente
16
Absolutamente malvado: convierte las etiquetas en GOTO. Suena como una característica de lenguaje que los hackers
rogarían
114
Ok, pero se supone que INTERCAL es divertido, esto no es realmente un "truco" sorprendente. ¡El compilador INTERCAL puede negarse a compilar el programa si no utiliza el PLEASEmodificador con la frecuencia suficiente!
Groo
10
Suena como AOP :)
akuhn
66
Lo que más me sorprende es que en el análisis de requisitos del sistema en el "Mundo de TI comercial", los COMEFROM en realidad se usan en archivos de texto que describen casos de uso. (en serio: algunos analistas aquí retrasaron una migración a toda la empresa a OpenOffice en lugar de a la Oficina de MS porque el primero no pudo hacer referencia a un "resultado" con la granularidad requerida en un enlace)
jsbueno
55
Groo: es peor. Use POR FAVOR con demasiada frecuencia y se niega a compilar su programa porque se está arrastrando (C-INTERCAL requiere que entre el 33% y el 66% de las declaraciones tengan modificadores POR FAVOR).
Vatine
160

No es realmente una característica del lenguaje, sino una falla de implementación: algunos compiladores de Fortran implementaron constantes mediante el uso de un grupo constante. Todos los parámetros fueron pasados ​​por referencia. Si llamó a una función, por ejemplo

f(1)

El compilador pasaría la dirección de la constante 1 en el grupo constante a la función. Si asignó un valor al parámetro en la función, cambiaría el valor (en este caso el valor de 1) globalmente en el programa. Causó un poco de rascarse la cabeza.

Richard Pennington
fuente
124
Oh. Entonces 2+2 puede ser igual 5(¡para valores muy grandes, 2por supuesto!).
Alok Singhal
12
um, ¿qué valor de 2 haría "2 + 2" == "5"? No sé ningún valor entero 2 puede asumir para que eso sea cierto.
Aaron
36
@earlz: sospecho que terminaría como un valor integral, de cualquier patrón de bits. Por otro lado, probablemente podría establecer 5 a 4 de esa manera (por 2+2lo que sería igual 5para valores pequeños de 5).
David Thornley
18
Disculpe, Alok, pero estamos hablando de FORTRAN temprano. No será cierto eso 2 + 2 = 5; eso será un error de sintaxis. Lo que será cierto es 2 + 2 .EQ. 5.
David Thornley
3
En Haskell, el siguiente fragmento se evalúa como 5: "let 2 + 2 = 5 in 2 + 2" :)
Tirpen
153

No sé si se puede considerar una función de lenguaje, pero, en C ++, casi cualquier error de compilación relacionado con las plantillas ofrece una buena cantidad de WTF a muchos programadores de C ++ en todo el mundo a diario :)

Dmitry
fuente
15
Está bien, la mayoría del código relacionado con las plantillas ya crea muchos WTF en todo el mundo.
Joris Timmermans
43
Oh ven ahora referencia indefinida a `std :: basic_ostream <char, std :: char_traits <char>> & std :: operator << <std :: char_traits <char>> (std :: basic_ostream <char, std :: char_traits <char> > &, char const *) '¡Es perfectamente legible!
Matt Greer
10
Una vez tuve un error de compilación relacionado con la plantilla que tenía cinco líneas, la más corta de las cuales tenía diecisiete mil caracteres (el clásico error 'no coincide para x', en un programa profundamente diseñado). Esa es la WTF, no la característica en primer lugar, las plantillas son maravillosas.
Andrew McGregor
111
Incluso si no hay ningún error, intente encontrar qué funciones tardan más con su generador de perfiles. Oh mira, esstd::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::vector< std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator>(std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::allocator<std::pair<int, std::complex> >)
rlbond
12
Creo que esto encaja aquí: echa un vistazo a STLFilt en bdsoft.com/tools/stlfilt.html para que la salida sea legible.
miedo el
150

Los muchos espacios de nombres de C:

typedef int i;

void foo()
{
    struct i {i i;} i;
    i: i.i = 3;
    printf( "%i\n", i.i);
}

O con personajes:

typedef char c;

void foo()
{
    struct c {c c;} c;
    c: c.c = 'c';
    printf( "%c\n", c.c);
}
Victor Hurdugaci
fuente
¿Cómo diablos esto compila sin ambigüedades?
Earlz
13
Los identificadores de etiqueta +1 para enumeraciones y estructuras son la parte más confusa de C imho. Pocas personas entienden por qué el lenguaje para escribir defina un puntero a una estructura se ve de la manera que lo hace.
Tadeusz A. Kadłubowski
11
Se compila porque cada uno de esos i tiene un espacio de nombres inequívoco debido al contexto.
Andrew McGregor
149

Diría que todo el espacio en blanco de Python es mi mejor característica de WTF. Es cierto, más o menos te acostumbras después de un tiempo y los editores modernos hacen que sea fácil de tratar, pero incluso después del desarrollo de Python a tiempo completo durante el año pasado, todavía estoy convencido de que fue una mala idea. He leído todo el razonamiento detrás de esto, pero honestamente, se interpone en mi productividad. No por mucho, pero sigue siendo una rebaba debajo de la silla de montar.

editar: a juzgar por los comentarios, algunas personas parecen pensar que no me gusta sangrar mi código. Esa es una evaluación incorrecta. Siempre he sangrado mi código sin importar el idioma y si me veo obligado a hacerlo o no. Lo que no me gusta es que es la sangría la que define en qué bloque está una línea de código. Prefiero delimitadores explícitos para eso. Entre otras razones, encuentro que los delimitadores explícitos hacen que sea más fácil cortar y pegar código.

Por ejemplo, si tengo un bloque con sangría de 4 espacios y lo pego al final de un bloque con sangría de 8 espacios, mi editor (¿todos los editores?) No tengo idea si el código pegado pertenece al bloque de 8 espacios o al exterior bloquear. OTOH, si tengo delimitadores explícitos, es obvio a qué bloque pertenece el código y cómo se debe (re) sangrar; lo hace buscando inteligentemente delimitadores de bloque.

edición 2: algunas personas que proporcionan comentarios parecen pensar que esta es una característica que odio o que creo que hace que Python sea un lenguaje pobre. De nuevo, no es cierto. Si bien no me gusta tanto, eso no viene al caso. La pregunta es sobre la característica más extraña del lenguaje, y creo que esto es extraño, en virtud de que es algo que muy, muy pocos (pero> 0) usan los idiomas.

Bryan Oakley
fuente
63
si se interpone en su productividad, entonces su código que no es de Python no puede ser muy legible ...
Tor Valamo
27
¿Qué idioma usaste antes de Python? ¿Cómo pudiste trabajar con otras personas y no sangrar ese idioma? ¿Cómo podría alguien soportar un código no sangrado en cualquier idioma? ¿Trabajaste en una habitación llena de genios que no necesitaban señales visuales en el código fuente?
S.Lott
53
+1 No podría estar más de acuerdo, si mi editor (Emacs) no puede sangrar mi código basado en algo distinto (como llaves / comenzar, finalizar / lo que sea) automáticamente, es realmente una tontería. Casi cualquier refactorización que haría en una función "más grande" puede ser una experiencia realmente mala.
Dmitry
83
Aquí está el trato: con cualquier otro idioma, puedo resaltar un bloque de código y que cualquier editor lo sangra correctamente. Pero debido a que el espacio en blanco ES, por definición, la sangría adecuada, pierde esa habilidad en Python. Por lo tanto, es más difícil mover el código o refactorizar las cosas. Y para la persona que afirma que el OP es la "primera persona en afirmar que fue un problema", bueno, tuve que mantener un código de Python por un tiempo y ahora usaré cualquier lenguaje sobre Python por esta misma razón.
Kendall Helmstetter Gelner
38
No me importa el espacio en blanco en Python. El WTF es que no se aplica de manera consistente. Puede mezclar niveles de sangría y pestañas, siempre que sean consistentes con sus hermanos. Entonces, el primer nivel de sangría puede ser un espacio, y el segundo puede ser dos TAB, y esto no es un error de sintaxis.
ieure
138

Luché un poco sobre esto:

1;

En perl, los módulos deben devolver algo verdadero .

miku
fuente
29
Algunos módulos pueden devolver valores basados ​​en operaciones de tiempo de ejecución. Si siempre devuelve verdadero, aún no tiene que ser poco creativo al respecto: returnvalues.useperl.at
Anónimo el
8
Si mi memoria Perl me sirve correctamente, el retorno verdadero de un módulo indica que el módulo se cargó correctamente. Devolver un valor falso significa que algo salió mal y evitaría que el programa se ejecute (si no se detecta).
Barry Brown
Esta es una declaración C válida también, solo que no se devuelve nada.
sigjuice
24
Mark Dominus escribió: "Raramente he usado lo 'Cogito ergo sum';que, como todos saben, es evidentemente cierto en todos los universos posibles. Esto garantiza la máxima portabilidad".
Greg Bacon el
PHP <?=1;?>devuelve 1. <?=true;?>devuelve 1. <?=false;?>devuelve nulo.
Talvi Watia
135

Me sorprende que nadie haya mencionado las 7 construcciones de bucle de Visual Basic .

For i As Integer = 1 to 10 ... Next
While True ... End While
Do While True ... Loop
Do Until True ... Loop
Do ... Loop While True
Do ... Loop Until True
While True ... Wend

Porque pegar un! en frente de su condicional se forma demasiado complicado!

Jeff Atwood
fuente
47
Deberían haberlo hecho " Whiley Whend", ya que hay algunas personas que pronuncian la palabra "mientras" con la aproximación velar labializada sin voz. Y, por supuesto, se alinea mejor, y el código que se alinea es agradable.
dreamlax
43
¿Por qué estás actuando tan raro?
Erik Forbes
48
Guau. Me pongo un poco nostálgico cuando lo pienso. La primera vez que usé VB fue cuando tenía 9 años. Soy de Suecia, y no era muy hábil en inglés en ese entonces. Ahora, hay una palabra sueca llamada "vänd" que básicamente significa "regresar" y que se pronuncia de manera similar a "wend". Por eso pensé que tenía mucho sentido ... :)
Emil H
61
! no está en VB, es "No". ¿O es eso? Sí, no, no lo es, pero no.
brianary
77
Sí, "Wend" es una palabra en inglés, que significa ir o continuar en algún curso o camino ( google.com/search?q=define%3A+wend ). No estoy seguro si eso ayuda o duele.
Michael Myers
134

Para aquellos que no saben, bces un "lenguaje de calculadora de precisión arbitraria", y lo uso con bastante frecuencia para cálculos rápidos, particularmente cuando los números involucrados son grandes ( $es el indicador):

$ bc -lq
12^345
20774466823273785598434446955827049735727869127052322369317059031795\
19704325276892191015329301807037794598378537132233994613616420526484\
93077727371807711237016056649272805971389591721704273857856298577322\
13812114239610682963085721433938547031679267799296826048444696211521\
30457090778409728703018428147734622401526422774317612081074841839507\
864189781700150115308454681772032

bcha sido un comando estándar de Unix durante mucho tiempo.

Ahora para la "función WTF". Esto es de man bc(énfasis mío):

salir : cuando se lee la declaración de salida, el procesador bc se termina, independientemente de dónde se encuentre la declaración de salida. Por ejemplo, "if (0 == 1) quit" hará que bc termine.

detener : la declaración de detención (una extensión) es una declaración ejecutada que hace que el procesador bc se cierre solo cuando se ejecuta. Por ejemplo, "if (0 == 1) halt" no hará que bc termine porque no se ejecuta la detención.

Alok
fuente
41
Yo uso Haskell para estas cosas.
Thomas Eding
8
Calculadora de Google?
igul222
77
Yo mismo comencé a usar Python, y la calculadora de Google es buena si estás en línea. Pero solía usar bcantes de eso, y quería escribir sobre bcmi publicación debido a las excelentes citas de la página de manual.
Alok Singhal
66
@Brian, entonces te gustará: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc(aunque tal vez ya lo sepas).
Alok Singhal
2
Yo uso irb (shell interactivo de Ruby). Pero en el pasado, siempre buscaba dc, como bc, pero usa el pulido inverso. Geektastic!
tragomaskhalos
134

Siempre me pregunté por qué el programa más simple era:

class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

Mientras que podría ser:

print "Hello World!"

Tal vez esto es para asustar a los estudiantes de informática en primer lugar ...

Didier Trosset
fuente
34
En algunos idiomas, "¡Hola, mundo!" Es un programa válido.
David Thornley
31
@SoMoS: en la mayoría de los lenguajes dinámicos como Python, Ruby o Perl, imprima "¡Hola mundo!" o alguna variación menor (por ejemplo, pone en lugar de imprimir) es un programa válido y completo.
Dave Kirby el
36
@Loadmaster: la implicación era que "todo el código pertenece a una clase" o "todo el código pertenece a una función" son restricciones innecesarias
Jimmy
19
El hecho de que un lenguaje imponga el uso de objetos no significa que se esté utilizando para una programación orientada a objetos adecuada. Es perfectamente posible programar de manera procesal en Java o C #. Para eso están los métodos estáticos.
jdmichal
68
Amo a las personas que piensan que OOP significa que todo debería ser un objeto.
Tor Valamo
132

JavaScript está orientado a objetos, ¿verdad? Entonces, los métodos de ejecución en cadenas literales y números deberían funcionar. Me gusta "hello".toUpperCase()y 3.toString(). Resulta que el segundo es un error de sintaxis, ¿por qué? Porque el analizador espera que un número seguido de un punto sea un literal de coma flotante. Ese no es el WTF, el WTF es que solo tienes que agregar otro punto para que funcione:

3..toString()

La razón es que el literal 3.se interpreta como 3.0y 3.0.toString()funciona bien.

Theo
fuente
8
Funciona de esta manera también en Python (prueba 3..__add__(4)). Por otra parte, creo que (3).__add__(4)es una forma mucho menos dañada de hacerlo :)
badp
49
Puedes hacer (3) .toString ()
Joseph Montanez
13
@ Gorilla3D: sí, pero esa no es una característica extraña del lenguaje, ¿verdad?
Theo
25
3.0.toString()hace que me piquen los ojos.
Ben Blank
18
127.0.0.1.toInt ()
berkus
130

En JavaScript:

2 == [2]

// Even stranger
2 == [[[2]]]

// And down-right nutty
var a = { "abc" : 1 };
a[[[["abc"]]]] === a["abc"]; // this is also true

Afortunadamente, la gente amable de stackoverflow.com me lo explicó todo: ¿por qué 2 == [2] en JavaScript?

Xavi
fuente
66
Es por eso que debes usar ===en su lugar.
Gumbo
10
Esto es útil por cierto, si tiene una función que devuelve un número y desea devolver algunos metadatos adicionales, puede devolver [número] con algunos campos adicionales agregados. El código simple nunca sabrá que no es un número real, y otro código puede obtener los metadatos requeridos.
Andrey Shchekin
36
@Andrey, excepto que si alguna vez tengo que mantener un código que haga lo que sugieres, muy pronto desearía la muerte de su autor.
Breton el
@ Andrew, ¡es una gran idea! También puedes usar Number(n)para hacer algo similar. Desafortunadamente en nuestras dos soluciones se ===rompe = (.
Xavi
55
+1: Me he considerado un programador experto de js, y nunca he sabido sobre esto: D
Thomas Eding
126

Mi característica más odiada es la sintaxis de cualquier archivo de configuración que incluye lógica condicional. Este tipo de cosas abundan en el mundo de Java (Ant, Maven, etc. ¡Sabes quién eres!).

Acabas de programar en lenguaje ac ** p, con depuración limitada y soporte de editor limitado.

Si necesita lógica en su configuración, el enfoque "Pythonic" de codificar la configuración en un lenguaje real es mucho mejor.

James Anderson
fuente
24
Tcl reinventó eso mucho antes de que Python naciera y Lisp lo inventó antes de eso. Así que no lo llamemos Pythonic, llamémoslo Emacs-ish.
slebetman
46
Vamos a llamarlo bien.
mletterle
30
AMÉN. Si su configuración o lenguaje de compilación se está completando, lo está haciendo mal. Te estoy mirando CMake / autotools.
Joseph Garvin el
16
Esto es exactamente para lo que Lua fue diseñado originalmente
Cogwheel
1
Bueno, si su código está en Python, entonces tener su archivo de configuración en Python es una gran idea, ya que simplemente importa el archivo y lee los atributos del módulo. Y obtienes el poder 100% Turing completo de Python en tu archivo de configuración.
Asmeurer
113

powerbasic (www.powerbasic.com) incluye la directiva del compilador:

# BLOAT {bloatsize}

esto aumenta el tamaño del ejecutable compilado por <bloatsize>bytes. esto se puso en el compilador en caso de que a las personas que crean el ejecutable no les guste el pequeño tamaño del ejecutable generado. hace que el EXE parezca más grande para competir con los lenguajes de programación hinchados :)

Don Dickinson
fuente
99
Jaja yuk. He oído que los desarrolladores ralentizan deliberadamente algunas operaciones (por ejemplo, una búsqueda) porque ayuda a las personas a creer que realmente está haciendo algo. Algo similar, supongo.
David
42
Esto me recuerda algo que leí recientemente. Estaban probando un FPS y decidieron aumentar el número de puntos de golpe que tenían los malos. Luego les preguntaron a los evaluadores cómo era la IA y juraron que era mucho más inteligente. Pero la IA no había cambiado, solo los puntos de golpe. Las personas tienen una cierta narrativa sobre el mundo en sus cabezas, y si entiendes y coinciden con sus expectativas, simplemente asumirán que valida su narrativa.
Nate CK
55
Solía ​​agregar mucha desaceleración adicional a mis programas para que parecieran que estaban haciendo algo complicado. De vuelta en la escuela primaria, eso es.
Matti Virkkunen
3
De vuelta en la escuela teníamos máquinas 80286 y en realidad tuve que escribir algunas rutinas de salida de pantalla en el ensamblaje para obtener una velocidad razonable (es decir, no rastrear).
berkus
77
@Nate CK, si la IA vive lo suficiente como para mostrar su IA, en realidad puede ser más inteligente, mientras que antes podría haber muerto demasiado rápido para demostrarlo.
zzzzBov