Qual è, secondo te, la caratteristica del linguaggio più sorprendente, bizzarra, strana o davvero "WTF" che hai riscontrato?
Per favore, solo una funzione per risposta.
Qual è, secondo te, la caratteristica del linguaggio più sorprendente, bizzarra, strana o davvero "WTF" che hai riscontrato?
Per favore, solo una funzione per risposta.
Risposte:
In C, le matrici possono essere indicizzate in questo modo:
a[10]
che è molto comune.
Tuttavia, la forma meno conosciuta (che funziona davvero!) È:
10[a]
il che significa lo stesso del precedente.
In JavaScript:
'5' + 3 gives '53'
Mentre
'5' - 3 gives 2
+
perché la concatenazione di archi è orribile
In JavaScript, il seguente costrutto
return
{
id : 1234,
title : 'Tony the Pony'
};
ritorna è un errore di sintassi a causa del subdolo inserimento implicito del punto e virgola sulla riga successiva dopo undefined
return
. Quanto segue funziona come ci si aspetterebbe però:
return {
id : 1234,
title : 'Tony the Pony'
};
Ancora peggio, funziona anche questo (almeno in Chrome):
return /*
*/{
id : 1234,
title : 'Tony the Pony'
};
Ecco una variante dello stesso problema che non genera un errore di sintassi, ma fallisce silenziosamente:
return
2 + 2;
Tabella di verità 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
Fonte: Doug Crockford
==
serve agli occhi del progettista del linguaggio?
==
avesse il significato di ===
, e poi ci fosse un altro operatore, qualcosa del genere ha ~=
permesso la coercizione del tipo.
Trigrafi in C e C ++.
int main() {
printf("LOL??!");
}
Questo verrà stampato LOL|
, perché la trigrafia ??!
viene convertita in |
.
Divertimento con il boxe automatico e la cache intera in 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
Una rapida occhiata al codice sorgente Java mostrerà quanto segue:
/**
* 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: il IntegerCache.high
valore predefinito è a 127
meno che non sia impostato da una proprietà.
Quello che succede con l'auto boxing è che sia foo che bar lo stesso oggetto intero recuperato dalla cache a meno che non sia stato esplicitamente creato: ad esempio foo = new Integer(42)
, quindi quando si confronta l'uguaglianza di riferimento, saranno veri piuttosto che falsi. Si sta utilizzando il modo corretto di confrontare il valore intero.equals;
Citando Neil Fraser (guarda la fine di quella pagina),
try {
return true;
} finally {
return false;
}
(in Java, ma il comportamento è apparentemente lo stesso in JavaScript e Python). Il risultato è lasciato come esercizio al lettore.
EDITED: Fintanto che siamo in materia considerare anche questo:
try {
throw new AssertionError();
} finally {
return false;
}
Control cannot leave the body of a finally clause
return
in finally
clausola.
APL (diverso da TUTTO), la possibilità di scrivere qualsiasi programma in una sola riga.
ad es. Conway's Game of Life in una riga in APL :
testo alternativo http://catpad.net/michael/APLLife.gif
Se quella linea non è WTF, allora niente lo è!
Ed ecco un video
Le cose strane per cui si possono usare i template C ++, meglio dimostrate da "Letterali analogici multidimensionali" che usano i template per calcolare l'area delle forme "disegnate". Il seguente codice è C ++ valido per un rettangolo 3x3
#include"analogliterals.hpp"
using namespace analog_literals::symbols;
unsigned int c = ( o-----o
| !
! !
! !
o-----o ).area;
Oppure, un altro esempio 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) );
Molte variabili integrate di Perl:
$#
- no un commento!$0
, $$
e$?
- proprio come le variabili shell con lo stesso nome$ˋ
, $&
e$'
- strane variabili corrispondenti$"
e $,
- strane variabili per i separatori di campi elenco e output$!
- come errno
un numero mastrerror(errno)
come una stringa$_
- la variabile invisibile, sempre usata e mai vista$#_
- numero indice dell'ultimo argomento della subroutine ... forse@_
- i (non) nomi della funzione corrente ... forse$@
- l'ultima eccezione sollevata%::
- la tabella dei simboli$:
, $^
, $~
, $-
, E $=
- a che fare con formati di output$.
e $%
- numero della riga di input, numero della pagina di output$/
e $\
- separatori di record di input e output$|
- controller di buffering di output$[
- cambia la base dell'array da 0 in base a 1 in base a 42: WHEEE!$}
- niente affatto, stranamente!$<
, $>
, $(
, $)
- UID e GID reali ed efficaci@ISA
- nomi delle superclassi dirette del pacchetto corrente$^T
- tempo di avvio dello script in secondi di epoca$^O
- nome del sistema operativo corrente$^V
- quale versione di Perl è questaC'è molto di più da dove provengono. Leggi l'elenco completo qui .
$[
variabile è la più malvagia di tutte.
perldoc perlvar
ogni cinque secondi. (Anche se lo confesso che la metà delle volte lo controllo pensando "So che c'è una variabile speciale che può fare questo per me, non ricordo quale ..." = P)
use English;
è che influisce sulle prestazioni di RegExp. Non sto inventando. perldoc.perl.org/English.html#PERFORMANCE
/$foo[bar]/
, la [bar]
parte è una classe di caratteri o un pedice dell'array @foo
? Grep perldata per la risposta terrificante.
PHP gestisce i valori numerici nelle stringhe . Vedi questa risposta precedente a una domanda diversa per tutti i dettagli ma, in breve:
"01a4" != "001a4"
Se hai due stringhe che contengono un numero diverso di caratteri, non possono essere considerate uguali. Gli zeri iniziali sono importanti perché si tratta di stringhe e non di numeri.
"01e4" == "001e4"
A PHP non piacciono le stringhe. Sta cercando qualsiasi scusa che può trovare per trattare i tuoi valori come numeri. Cambia leggermente i caratteri esadecimali in quelle stringhe e improvvisamente PHP decide che queste non sono più stringhe, sono numeri in notazione scientifica (a PHP non importa che tu abbia usato le virgolette) e sono equivalenti perché gli zeri iniziali vengono ignorati per i numeri. Per rafforzare questo punto scoprirai che PHP valuta anche "01e4" == "10000"
come vero perché si tratta di numeri con valori equivalenti. Questo è un comportamento documentato, semplicemente poco sensato.
Diamo un voto a tutte le lingue (come PL / I) che hanno cercato di eliminare le parole riservate.
Dove altro potresti legalmente scrivere espressioni così divertenti come:
IF IF THEN THEN = ELSE ELSE ELSE = THEN
( IF
, THEN
, ELSE
Sono i nomi delle variabili)
o
IF IF THEN THEN ELSE ELSE
( IF
è una variabile THEN
e ELSE
sono subroutine)
La 'caratteristica' di conversione ottale JavaScript è buona da conoscere:
parseInt('06') // 6
parseInt('07') // 7
parseInt('08') // 0
parseInt('09') // 0
parseInt('10') // 10
Maggiori dettagli qui .
In C si può intrecciare un do / while con un'istruzione switch. Ecco un esempio di memcpy usando questo metodo:
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);
}
}
while
alla fine è un (condizionale) di JMP
nuovo a do
, il che spiega perché puoi saltare il do
e finire comunque nel ciclo.
Algol passa per nome (illustrato usando la sintassi 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]);
}
def f(j : => int)
)
... 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]; } }); }
?
In Python:
>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
Non un WTF, ma una funzione utile.
(10 > 5 > 1) != ((10 > 5) > 1)
in Python.
(funct_a(5)+5 > b > funct_a(5))
chiama solo funct_a(5)
una volta. È una GRANDE funzionalità!
funct_a
verrà chiamato due volte in questo esempio. In b > funct_a(5) > c
esso verrà chiamato solo una volta, invece di b > funct_a(5) and funct_a(5) > c
.
In Java:
int[] numbers() {
return null;
}
Può essere scritto come:
int numbers() [] {
return null;
}
const T*
e T const*
sono equivalenti, è T* const
quello che rappresenta il puntatore. Inoltre, odio i caratteri sans.
numbers()[2]
è una dichiarazione legale.
INTERCAL è probabilmente il miglior compendio di funzionalità linguistiche più strane. Il mio preferito è l' istruzione COMEFROM che è (quasi) l'opposto di GOTO.
COMEFROM è all'incirca l'opposto di GOTO in quanto può portare lo stato di esecuzione da qualsiasi punto arbitrario nel codice a un'istruzione COMEFROM. Il punto nel codice in cui si verifica il trasferimento dello stato viene generalmente assegnato come parametro a COMEFROM. Se il trasferimento avviene prima o dopo l'istruzione nel punto di trasferimento specificato dipende dalla lingua utilizzata. A seconda della lingua utilizzata, più COMEFROM che fanno riferimento allo stesso punto di partenza possono essere non validi, non deterministici, essere eseguiti in una sorta di priorità definita o persino indurre un'esecuzione parallela o simultanea come visto in Threaded Intercal. Un semplice esempio di un'istruzione "COMEFROM x" è un'etichetta x (che non deve essere posizionata fisicamente in alcun punto vicino al corrispondente COMEFROM) che funge da "botola". Quando l'esecuzione del codice raggiunge l'etichetta, il controllo viene passato all'istruzione che segue COMEFROM. L'effetto di questo è principalmente quello di rendere estremamente difficile il debug (e la comprensione del flusso di controllo del programma), poiché non vi è alcuna indicazione vicino all'etichetta che il controllo salti misteriosamente a un altro punto del programma.
PLEASE
modificatore abbastanza spesso!
Non proprio una caratteristica del linguaggio, ma un difetto di implementazione: alcuni primi compilatori Fortran implementavano costanti usando un pool costante. Tutti i parametri sono stati passati per riferimento. Se hai chiamato una funzione, ad es
f(1)
Il compilatore passerebbe l'indirizzo della costante 1 nel pool di costanti alla funzione. Se si assegna un valore al parametro nella funzione, si cambierà il valore (in questo caso il valore 1) a livello globale nel programma. Ha causato qualche graffio alla testa.
2+2
può eguagliare 5
(per valori molto grandi 2
ovviamente!).
2+2
sarebbe uguale 5
per piccoli valori di 5
).
2 + 2 = 5
; sarà un errore di sintassi. Ciò che sarà vero è 2 + 2 .EQ. 5
.
Non so se può essere considerata una funzionalità del linguaggio, ma, in C ++, quasi ogni errore del compilatore relativo ai modelli fornisce una buona quantità di WTF a molti programmatori C ++ in tutto il mondo su base giornaliera :)
std::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> >)
I molti spazi dei nomi di C:
typedef int i;
void foo()
{
struct i {i i;} i;
i: i.i = 3;
printf( "%i\n", i.i);
}
O con personaggi:
typedef char c;
void foo()
{
struct c {c c;} c;
c: c.c = 'c';
printf( "%c\n", c.c);
}
Direi che l'intera cosa degli spazi bianchi di Python è la mia più grande caratteristica di WTF. È vero, ti ci abitui più o meno dopo un po 'e i moderni editor lo rendono facile da gestire, ma anche dopo lo sviluppo del pitone principalmente a tempo pieno per l'anno passato, sono ancora convinto che fosse una cattiva idea. Ho letto tutto il ragionamento alla base, ma onestamente, mi ostacola la mia produttività. Non di molto, ma è ancora una sbavatura sotto la sella.
modificare: giudicare dai commenti, alcune persone sembrano pensare che non mi piace rientrare nel mio codice. Questa è una valutazione errata. Ho sempre indentato il mio codice, non importa quale sia la lingua e se sono costretto o meno. Quello che non mi piace è che è il rientro che definisce in quale blocco si trova una riga di codice. Preferisco i delimitatori espliciti per quello. Tra le altre ragioni, trovo che i delimitatori espliciti rendano più semplice tagliare e incollare il codice.
Ad esempio, se ho un blocco con rientro di 4 spazi e lo incollo alla fine di un blocco con rientro di 8 spazi, il mio editor (tutti gli editor?) Non ha idea se il codice incollato appartiene al blocco di 8 spazi o all'esterno bloccare. OTOH, se ho delimitatori espliciti è ovvio a quale blocco appartiene il codice e come dovrebbe essere (ri) rientrato - lo fa cercando in modo intelligente i delimitatori di blocco.
modifica 2: alcune persone che forniscono commenti sembrano pensare che questa sia una caratteristica che odio o che ritenga che Python sia un linguaggio scadente. Ancora una volta, non è vero. Anche se non mi piace così tanto, non è questo il punto. La domanda riguarda la strana caratteristica del linguaggio, e penso che sia strano, in quanto si tratta di qualcosa che molto, pochissime (ma> 0) lingue usano.
Ho faticato un po 'su questo:
1;
In perl, i moduli devono restituire qualcosa di vero .
'Cogito ergo sum';
che, come tutti sanno, è evidentemente vero in tutti i possibili universi. Ciò garantisce la massima portabilità".
<?=1;?>
restituisce 1. <?=true;?>
restituisce 1. <?=false;?>
restituisce null.
Sono sorpreso che nessuno abbia menzionato i costrutti a 7 loop di 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
Perché attaccare un! di fronte al vostro condizionale è modo troppo complicato!
While
e Whend
", dal momento che ci sono alcune persone che pronunciano la parola "while" con l'approssimativo velare labeless senza voce. E ovviamente si allinea meglio, e il codice che fa la fila è carino.
Per chi non lo sapesse, bc
è un "linguaggio di calcolatrice di precisione arbitrario", e lo uso abbastanza spesso per calcoli rapidi, in particolare quando i numeri coinvolti sono grandi ( $
è il prompt):
$ bc -lq
12^345
20774466823273785598434446955827049735727869127052322369317059031795\
19704325276892191015329301807037794598378537132233994613616420526484\
93077727371807711237016056649272805971389591721704273857856298577322\
13812114239610682963085721433938547031679267799296826048444696211521\
30457090778409728703018428147734622401526422774317612081074841839507\
864189781700150115308454681772032
bc
è stato un comando Unix standard per molto tempo.
Ora per la "funzione WTF". Questo è da man bc
(enfasi mia):
quit : quando viene letta l'istruzione quit, il processore bc viene terminato, indipendentemente da dove si trova l'istruzione quit. Ad esempio, "if (0 == 1) quit" farà terminare bc.
halt : l'istruzione halt (un'estensione) è un'istruzione eseguita che provoca la chiusura del processore bc solo quando viene eseguita. Ad esempio, "if (0 == 1) halt" non farà terminare bc perché l'arresto non viene eseguito.
bc
prima e volevo scrivere bc
nel mio post a causa delle grandi citazioni dalla pagina man.
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
(anche se potresti già saperlo).
Mi sono sempre chiesto perché il programma più semplice fosse:
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Considerando che potrebbe essere:
print "Hello World!"
Forse questo è per spaventare gli studenti di informatica in primo luogo ...
JavaScript è orientato agli oggetti, giusto? Quindi i metodi in esecuzione su stringhe e numeri letterali dovrebbero funzionare. Mi piace "hello".toUpperCase()
e 3.toString()
. Si scopre che il secondo è un errore di sintassi, perché? Perché il parser si aspetta che un numero seguito da un punto sia letterale in virgola mobile. Questo non è il WTF, il WTF è che devi solo aggiungere un altro punto per farlo funzionare:
3..toString()
Il motivo è che il letterale 3.
viene interpretato come 3.0
e 3.0.toString()
funziona bene.
3..__add__(4)
). Poi di nuovo penso che (3).__add__(4)
sia un modo molto meno
3.0.toString()
mi fa prudere gli occhi.
In JavaScript:
2 == [2]
// Even stranger
2 == [[[2]]]
// And down-right nutty
var a = { "abc" : 1 };
a[[[["abc"]]]] === a["abc"]; // this is also true
Fortunatamente le persone gentili su stackoverflow.com mi hanno spiegato tutto: perché 2 == [2] in JavaScript?
===
invece.
Number(n)
qualcosa di simile. Purtroppo in entrambe le nostre soluzioni si ===
rompe = (.
La mia più grande caratteristica odiata è qualsiasi sintassi del file di configurazione che includa la logica condizionale. Questo genere di cose è diffuso nel mondo Java (Ant, Maven, ecc. Sai chi sei!).
Finisci per programmare in un linguaggio ac ** p, con debugging limitato e supporto editor limitato.
Se hai bisogno di logica nella tua configurazione, l'approccio "Pythonic" di codificare la configurazione in un linguaggio reale è molto meglio.
powerbasic (www.powerbasic.com) include la direttiva del compilatore:
# BLOAT {bloatsize}
ciò aumenta la dimensione dell'eseguibile compilato di <bloatsize>
byte. questo è stato inserito nel compilatore nel caso in cui alle persone che creano l'eseguibile non piaccia la piccola dimensione dell'eseguibile generato. fa sembrare EXE più grande competere con linguaggi di programmazione gonfiati :)