Najdziwniejsza funkcja językowa


974

Jaka jest, Twoim zdaniem, najbardziej zaskakująca, dziwna, dziwna lub naprawdę „językowa” cecha, z jaką się spotkałeś?

Proszę tylko jedną funkcję na odpowiedź.


5
@gablin Myślę, że jeśli połączysz ograniczniki LISP z wyrażeniem regularnym PERL za pomocą parsowania javascript,
pokryłbyś

Odpowiedzi:


1859

W C tablice można indeksować w następujący sposób:

a[10]

co jest bardzo powszechne.

Jednak mniej znana forma (która naprawdę działa!) To:

10[a]

co oznacza to samo co powyżej.


758
to dlatego, że [10] oznacza * (a + 10) ... a 10 [a] oznacza * (10 + a) :)
Michel Gokan

77
Nie zapomnij „Hello World” [i]. Albo ja [„Hello World”]
Richard Pennington,

167
Albo, bardziej użytecznie "0123456789abcdef" [x & 0xf]
Bagnet

17
@frunsi: Zawsze działa zgodnie z oczekiwaniami. Dodanie wskaźnika nie jest tym samym, co proste dodanie liczby całkowitej na adresach. Jest przemienny bez względu na rozmiar, o którym mowa.
R. Martinho Fernandes,

12
@mcv - a [10] to to samo co „* (a + 10)”, gdzie wyrażenie „a + 10” jest arytmetyką wskaźnika (a ponieważ a jest krótkie, w twoim przykładzie, + 10 oznacza „zacznij od” adres a i przenieś 10 skrótów, tj. 20 bajtów). Wyrażenie 10 [a] jest interpretowane jako „* (10 + a)”, gdzie „10 + a” jest również wskaźnikiem arytmetycznym i jest traktowane dokładnie tak samo.
Edan Maor,

1292

W JavaScript:

 '5' + 3 gives '53'

Natomiast

 '5' - 3 gives 2

81
Pamiętam, kiedy po raz pierwszy zacząłem używać javascript, używając tego rodzaju techniki do dodawania liczb w ciągach: „111” - - „222” daje 333, a „111” + „222” daje „111222”.
Callum Rogers

112
+bo łączenie strun jest okropne
Matteo Riva

416
+ dla concat nie jest problemem. Słabe pisanie jest.
FogleBird

270
@FogleBird Żaden z nich nie jest tak naprawdę problemem. To tylko połączenie tych dwóch z niespójnymi zasadami przymusu.
TM.

70
Zasadniczo więc + jest konkatatowany, gdy zaangażowany jest łańcuch. Dlaczego nie mogą napisać czegoś takiego jak „123456” - 456 = „123”? To by było interesujące.
Jimmie Lin

872

W JavaScript następująca konstrukcja

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

returnundefined jest błędem składniowym wynikającym z podstępnego niejawnego wstawiania średnika w nowej linii po return. Następujące działa jednak tak, jak można się spodziewać:

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

Co gorsza, ten również działa (przynajmniej w Chrome):

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

Oto wariant tego samego problemu, który nie powoduje błędu składniowego, po prostu po cichu kończy się niepowodzeniem:

return
    2 + 2;

225
Wstawianie średnika jest jedną z najbardziej złych części JavaScript.

230
Zawsze napotykasz problemy, projektując funkcje językowe przy założeniu, że Twoi użytkownicy będą w większości idiotami.
Rob Van Dam

8
Naprawdę miałem ten problem, ponieważ będąc programistą c #, umieściłem klamrę w nowej linii. Zajęło mi godziny, aby zrozumieć, na czym polega problem. Nawet kiedy rozwiązałem problem, nie wiedziałem, na czym polega problem, dopóki nie przeczytałem twojej odpowiedzi!
Fedor Hajdu,

24
Nick Retallack: Ponieważ ze względu na składnię nawiasów klamrowych i średników w języku C JavaScript nie jest wcale oczywiste, że znaki nowej linii są znaczące.
Tamas Czinege

19
Jeśli nie powinieneś używać stylu C podczas programowania w JavaScript, wybranie składni w stylu C było dość przewrotne dla projektantów języka JavaScript.
Ryan Lundy,

795

Tabela prawdy 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

Źródło: Doug Crockford


237
Dobrze, że Javascript ma operator ===.
Anonimowy

65
Jaki cel ==służy w oczach projektanta języka?
Chris S

137
Zagubieni ludzie.
Javier

123
Byłoby miło, gdyby ==miał znaczenie ===, a wtedy byłby inny operator, coś takiego ~=pozwalało na przymus typu.
TM.

18
@Otto Właściwie, skoro wychodzimy na manowce, jego przykład pokazuje, że == nie jest symetryczny. W tej chwili nie widziałem, jak komutatywność byłaby określona dla relacji binarnej.
PeterAllenWebb

660

Trigrafie w C i C ++.

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

Spowoduje to wydrukowanie LOL|, ponieważ kaligraf ??!jest konwertowany na |.


71
Szybki! Powiedz wszystkim programistom C / b /!
Esteban Küber

235
Trójkąty są niesamowite, ponieważ możesz być pewien, że nikt nigdy się nie dowie, co ??? będzie oznaczać od Google, nie znając już nazwy.
zaratustra

56
Trygrysy są domyślnie wyłączone w GCC.
sastanin

360
Umożliwiają one użycie „operatora WTF”: (foo ()! = ERROR) ??! ??! cerr << „Wystąpił błąd” << endl;
user168715

57
Trójkąty były złem koniecznym po ich wprowadzeniu. Niektóre platformy po prostu nie zawierały pewnych znaków kluczowych dla języka, więc były to albo „trigrafy”, albo „nie możesz mieć kompilatora C pod koniec okresu wypowiedzenia, więc idź użyć asemblera”. Sprawdź opis Stroustrupa w „The C ++ Programming Language”.
Euro Micelli,

573

Zabawa z automatycznym boksem i całkowitą pamięcią podręczną w Javie:

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

Wyjaśnienie

Szybkie spojrzenie na kod źródłowy Java spowoduje wyświetlenie następujących informacji:

/**
 * 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);
}

Uwaga: wartość IntegerCache.high domyślna to 127chyba, że ​​jest ustawiona przez właściwość.

To, co dzieje się z automatycznym bokowaniem, polega na tym, że zarówno foo, jak i słupek tego samego obiektu liczb całkowitych pobranego z pamięci podręcznej, chyba że jest to jawnie utworzone: np. foo = new Integer(42)Dlatego, porównując równość referencji, będą one prawdziwe, a nie fałszywe. Stosuje się właściwy sposób porównywania wartości całkowitych.equals;


31
Zajęło mi kilka sekund, aby zrozumieć, dlaczego ... java musi przechowywać pulę instancji Integer dla wartości od -128 do 128, w przeciwnym razie przydziela nową Integer, prawda?
Mike Akers

18
Należy jednak pamiętać, że jeśli podasz nową liczbę całkowitą (42), nie będzie ona korzystać z instancji z puli, więc foo == pasek zmieni wartość na false
z -

10
Zawsze używam liczb całkowitych zamiast liczb całkowitych, jeśli to możliwe, ale jeśli musiałbym użyć liczb całkowitych z jakiegoś powodu, czy powinienem po prostu użyć .equals () zamiast ==?
MatrixFrog,

246
Tak się cieszę, że jestem programistą C #.

87
@Will: C # ma kilka bardzo podobnych błędów. Zobacz blogs.msdn.com/jmstall/archive/2005/03/06/386064.aspx
spookylukey

373

Cytując Neila Frasera (spójrz na koniec tej strony),

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

(w Javie, ale zachowanie jest podobno w JavaScript i Python). Wynik pozostawia się czytelnikowi jako ćwiczenie.

ZMIENIONO: Tak długo, jak zajmujemy się tym tematem, rozważ również to:

try {
    throw new AssertionError();
} finally {
    return false;
}

42
+1. Z jakiegoś powodu uważam to za zabawne i nie mogę przestać chichotać.
poza

153
Na szczęście C # nie pozwala na takie szaleństwo ...Control cannot leave the body of a finally clause
Richard Ev

64
To zwraca, fałsz, prawda? Może to wyglądać jak WTF (i być może jest to jeden), ale żyję zgodnie z zasadą: W końcu zawsze wygrywa, chyba że wcześniej zawiesisz Maszynę.
Michael Stum

28
Szczerze mówiąc, obwiniam ładne wytłumaczenie TDWTF za to, że w końcu zawsze wygrywa, chyba że szarpniesz przewód zasilający: thedailywtf.com/Articles/My-Tales.aspx
Michael Stum

22
Nie jestem pewien, jaki kod powinien zwrócić w tym przypadku. Ale jestem absolutnie pewien, że nie należy umieszczać returnw finallyklauzuli.
jfs

325

APL (oprócz WSZYSTKICH), możliwość napisania dowolnego programu w jednym wierszu.

np . Gra życia Conwaya w jednej linii w APL :

alt text http://catpad.net/michael/APLLife.gif

Jeśli ta linia nie jest WTF, to nic nie jest!

A oto film


19
Uwielbiam APL. Ach, radość spędzania całego popołudnia na pisaniu pół wiersza kodu! Pierwszą rzeczą, którą zrobię, gdy dostanę klawiaturę, na której mogę zaprogramować wyświetlane litery, jest ponowne zapoznanie się z APL.
Daniel C. Sobral

24
Wygląda jak język dla Greków.
Esko

45
@Erik: Piszę kod, który dotyczy wyłącznie tego, czego chcesz, a nie tego, jak się tam dostać. Wyrażania kodu jako pojedynczego wyrażenia. To jak najlepszy idealny krój katany. Oczywiście w prawdziwej walce wolałbym mieć broń.
Daniel C. Sobral

7
@Daniel: Całe popołudnie spędzasz na pisaniu linii kodu ... i cały tydzień na czytaniu linii kodu. ;-)
Jürgen A. Erhard

93
APL byłby niesamowity do zobaczenia w filmie akcji science fiction. Mogę sobie wyobrazić, że ktoś siedzi przy trójkolorowym terminalu, mrucząc: „Przekształć wektor pocisków wroga ... transponuj ... pi razy logarytm ... oceniaj - i - wykonuj!” następnie wybuchy i wiwaty.
Joey Adams

321

Dziwne rzeczy, do których można wykorzystać szablony C ++, najlepiej pokazane w „Wielowymiarowych literałach analogowych”, które używają szablonów do obliczania obszaru „narysowanych” kształtów. Poniższy kod jest poprawnym C ++ dla prostokąta 3x3

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

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

Lub inny przykład z kostką 3D:

  assert( ( o-------------o
            |L             \
            | L             \
            |  L             \
            |   o-------------o
            |   !             !
            !   !             !
            o   |             !
             L  |             !
              L |             !
               L|             !
                o-------------o ).volume == ( o-------------o
                                              |             !
                                              !             !
                                              !             !
                                              o-------------o ).area * int(I-------------I) );

18
Chociaż literały analogowe Eelis są świetne, czy są dziwną cechą językową , czy po prostu dziwnym sposobem korzystania z tej funkcji?

85
Rzeczywistym WTF będzie błąd kompilatora generowany przez jeden z tych, które są zniekształcone.
Andrew McGregor,

6
Jak chory jest to ... obudź mnie ponownie, gdy istnieje wersja AnalogLiterals, która obsługuje obracanie literału wokół osi X, Y i Z w Eclipse ... teraz, co nadałoby „programowaniu wizualnemu” nowe prawdziwe znaczenie.
TheBlastOne

2
Czy kolejność znaków o i L jest ważna?
Ming-Tang,

4
Kolejność ma znaczenie, ponieważ szablony w kreatywny sposób wykorzystują przeciążanie operatorów (nie rób tego z prawdziwym kodem, niewłaściwe użycie operatorów sprawia, że ​​kod jest trudny do odczytania)
josefx 14.01.11

292

Wiele wbudowanych zmiennych Perla:

  • $# - bez komentarza!
  • $0, $$ i $?- podobnie jak zmienne powłoki o tej samej nazwie
  • , $& i $'- dziwne pasujące zmienne
  • $" i $, - dziwne zmienne dla separatorów list i pól wyjściowych
  • $! - lubić errno liczba, ale strerror(errno)jako ciąg
  • $_- zmienna Stealth, zawsze i nigdy nie widziałem
  • $#_ - numer indeksu ostatniego argumentu podprogramu ... może
  • @_ - (nie) nazwy bieżącej funkcji ... może
  • $@ - ostatni podniesiony wyjątek
  • %:: - tablica symboli
  • $:, $^, $~, $-, I$= - coś zrobić z formatów wyjściowych
  • $. i $% - numer linii wejściowej, numer strony wyjściowej
  • $/ i $\ - separatory rekordów wejściowych i wyjściowych
  • $| - kontroler buforowania wyjścia
  • $[ - zmień bazę macierzy z 0 na 1 na 42: WHEEE!
  • $} - nic w tym dziwnego!
  • $<, $>, $(,$) - realne i efektywne UID i GID
  • @ISA - nazwy bezpośrednich nadklas bieżącego pakietu
  • $^T - czas uruchomienia skryptu w epokach sekund
  • $^O - aktualna nazwa systemu operacyjnego
  • $^V - jaka to wersja Perla

Tam jest o wiele więcej. Przeczytaj pełną listę tutaj .


83
$[Zmienna jest najbardziej zło z nich wszystkich.
Brad Gilbert

24
Z pewnością doceniłbym to, gdyby Perl 6 był czymś, w co mógłbym kodować bez konieczności sprawdzania perldoc perlvarco pięć sekund. (Chociaż przyznaję się, że przez pół czasu sprawdzam to, myśląc: „Wiem, że istnieje specjalna zmienna, która może to dla mnie zrobić, ale po prostu nie pamiętam, która ...” = P)
Chris Lutz

17
Problem use English;polega na tym, że wpływa to na wydajność RegExp. Nie wymyślam tego. perldoc.perl.org/English.html#PERFORMANCE
Dave Webb

13
@Dave: to nie jest problem z powodu opcji -no_match_vars na stronie, którą podłączyłeś. @Brad: $ [jest tak złe. Intencją tego jest zło, tak, ale to nawet nie działa! @Artem: from perlvar „Identyfikatory Perla rozpoczynające się cyframi, znakami kontrolnymi lub znakami interpunkcyjnymi są zwolnione z efektów deklaracji pakietu i zawsze muszą znajdować się w pakiecie głównym; są również zwolnione z surowych błędów„ vars ”.” Oznacza to, że @ $ zostanie utworzone i przypisane bez błędu nawet w przypadku zwężenia. Ugh!
rjh

4
@Brian: Jak proponujesz nauczyć się składni, gdy sama oficjalna dokumentacja stwierdza, że ​​istnieją okoliczności, w których interpreter Perla heurystycznie zgaduje, co oznacza sekwencja znaków? Np /$foo[bar]/, jest [bar]częścią klasy znak lub indeks do tablicy @foo? Grep perldata za przerażającą odpowiedź.
j_random_hacker

289

Obsługa wartości liczbowych w łańcuchach przez PHP . Zobacz poprzednią odpowiedź na inne pytanie, aby uzyskać szczegółowe informacje, ale w skrócie:

"01a4" != "001a4"

Jeśli masz dwa ciągi znaków, które zawierają inną liczbę znaków, nie można ich uznać za równe. Zera wiodące są ważne, ponieważ są to ciągi, a nie liczby.

"01e4" == "001e4"

PHP nie lubi napisów. Poszukuje jakiejkolwiek wymówki, by traktować swoje wartości jak liczby. Zmień nieznacznie znaki szesnastkowe w tych ciągach i nagle PHP decyduje, że to już nie są ciągi, są to liczby w notacji naukowej (PHP nie obchodzi, że użyłeś cudzysłowów) i są one równoważne, ponieważ zera są ignorowane dla liczb. Aby wzmocnić ten punkt, przekonasz się, że PHP również ocenia "01e4" == "10000"jako prawdziwe, ponieważ są to liczby o równoważnych wartościach. Jest to udokumentowane zachowanie, po prostu nie jest zbyt rozsądne.


56
Wystarczy użyć === i! ==. Którego i tak należy użyć, chyba że potrzebne jest luźne porównanie typów.
Dykam

14
@Dykam, jeśli podążysz za linkiem do pełniejszej odpowiedzi, zobaczysz, że zwróciłem uwagę na użycie operatora ===.
Dan Dyer

18
Słabe pisanie znów uderza!
gillonba

43
Zawsze wiedziałem, że PHP jest grzechem. Do tej pory nie zdawałem sobie sprawy, że to grzech niewybaczalny: D
Thomas Eding

2
Powinni techników, którzy powinni używać === w dowolnej książce programistycznej lub samouczku. Dodano notatkę: w źle napisanej aplikacji PHP byłem w stanie podać jako hasło wszystko, co zostało przeanalizowane jako ten sam numer.
Pepijn

282

Głosujmy na wszystkie języki (takie jak PL / I), które próbowały pozbyć się słów zastrzeżonych.

Gdzie indziej możesz napisać takie zabawne wyrażenia, jak:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

( IF, THEN,ELSE Są nazwy zmiennych)

lub

IF IF THEN THEN ELSE ELSE

( IFjest zmienną THENi ELSEsą podprogramami)


1
@quark: to osobna odpowiedź na to! ;) ... (i tak, możesz programować w języku angielskim, po prostu wdróż go jako .ppt na innych programistach.;)
Macke

28
@RoadieRich jedna grupa bawołów nie pochodzi wprost z Buffalo, są one po prostu bawołem nieokreślonym.
Jürgen A. Erhard

18
John, w którym James był, miał lepszy wpływ na nauczyciela.
GameFreak,

4
Pewnego dnia widziałem kilku wytwórców znaków przed fabryką lodów Bena i Jerrysa. Krytykowałem ich pracę, powiedziałem im, że nie ma wystarczająco dużo miejsca między Benem i oraz i i Jerrysem.
Tom Gullen,

9
Może będzie to potrzebne w przyszłych programach czasowych. JEŚLI TO = TERAZ && GDZIE = TUTAJ KIEDY = NASTĘPNIE TERAZ = INNE
Kelly S. Francuski

282

„Funkcja” konwersji ósemkowej JavaScript jest dobra, o której warto wiedzieć:

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

Więcej informacji tutaj .


60
Utknąłem na błędzie, że wszystkie liczby działały oprócz 8 i 9 !! Szaleję !!! Dzięki Brian!
Faruz

10
@Yada Nie masz na myśli ósemki? Szesnastkowy to 0x.
luiscubal

48
I dlatego parseInt pobiera (opcjonalnie) dodatkowy argument :).
LiraNuna,

10
wiodące 0 oznacza liczbę ósemkową. ponieważ 8 nie jest poprawną cyfrą
ósemkową

22
... i parsować („010”) -> 8 tylko po to, aby się zdezorientować.
Richard Gadsden

213

Urządzenie Duffa w C!

W C można przeplatać instrukcję do / while z instrukcją switch. Oto przykład memcpy przy użyciu tej metody:

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);
    }
}

9
Urządzenie Duffa jest prawdopodobnie dobrym powodem, dla którego instrukcja switch domyślnie nie ma przerwy ;-) Jednak nie widziałem jeszcze żadnego innego dobrego zastosowania przełącznika i pętli z przeplotem - ale prawdopodobnie istnieje. Och, czekaj, tak, jest jeszcze jedno zastosowanie: kortyny i protole.
Frunsi

16
@frunsi: „Urządzenie Duffa jest prawdopodobnie dobrym powodem, dla którego instrukcja switch nie ma domyślnie przerwy” - Zawsze ustawiaj zwykły przypadek jako domyślny. Nie powiedziałbym dokładnie, że jest to powszechny przypadek.
BlueRaja - Danny Pflughoeft

6
@mcv prawdopodobnie najłatwiejszy, jeśli spróbujesz odczytać go jako kod asemblera, tzn. whilena końcu jest (warunkowy) JMPpowrót do do, co wyjaśnia, dlaczego możesz pominąć doi nadal kończyć w pętli.
wds

14
Należy pamiętać, że urządzenie Duffa generalnie generuje kod WORSE niż normalna instrukcja zapętlania dla współczesnych kompilatorów, które wiedzą (lepiej) zapętlać rozwijanie niż można ręcznie.
Billy ONeal

37
@frunsi: Sam Duff, publikując go, stwierdził coś w stylu: „Zdecydowanie stanowi to argument w dyskusji, czy przełącznik powinien się domyślnie upaść, ale nie jestem pewien, czy argument jest za, czy przeciw”.
SF.

204

Algol podaje nazwę (ilustrowane składnią 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]);
}

33
Jeśli się nad tym zastanowić, to rzeczywiście ma jakiś pokręcony sens
RCIX

90
To jest ostateczne „podanie przez odniesienie”.
Dykam

3
Jest to możliwe w Scala ( def f(j : => int))
Dario

10
Więc to jest coś takiego ... 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
W rzeczywistości jest to całkiem proste: generujesz niewielki fragment kodu (zwykle nazywany „thunk”, stąd moja gra słów powyżej), który oblicza adres wynikający z wyrażenia, w tym przypadku i [i]. Wskaźnik do tej funkcji jest przekazywany do wywoływanej funkcji, która następnie używa jej do obliczania bieżącego adresu przy każdym dostępie do parametru.
Richard Pennington,

189

W Pythonie:

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

Nie WTF, ale przydatna funkcja.


176
Chciałbym, aby każdy inny język miał tę funkcję
vava

32
Podobnie jak w przypadku prawie każdej fajnej funkcji Pythona, wygląda na to, że Guido po prostu ALGOLIZOWALI składnię fajnej funkcji Lisp. :-)
Ken

4
Geoffrey, jest to funkcja (10 > 5 > 1) != ((10 > 5) > 1)w Pythonie.
sastanin

18
Ponadto ocenia tylko raz, więc (funct_a(5)+5 > b > funct_a(5))dzwoni tylko funct_a(5)raz. To WIELKA funkcja!
Khelben

57
@Khelben: Nie, funct_aw tym przykładzie zostanie wywołany dwukrotnie. W b > funct_a(5) > czostanie wywołana tylko raz, choć w przeciwieństwie do b > funct_a(5) and funct_a(5) > c.
Baffe Boyois,

189

W Javie:

int[] numbers() {
  return null;
}

Można zapisać jako:

int numbers() [] {
  return null;
}

23
Łał! Chciałbym być muchą na ścianie, kiedy ta składnia tablicowa została zaprojektowana!
Adam Paynter

29
Nie chcę tego mówić, ale WTF jest spójnym rozszerzeniem systemu typu C. Gdyby funkcje C mogły zwracać tablice, to tak by to wyglądało. Ten ładniejszy to naruszenie spójności, aby uczynić go bardziej czytelnym. Podobnie jak „const char * var” vs „char const * var”.
Gordon Wrigley,

15
@Adam - W rzeczywistości ma sens, gdy weźmie się pod uwagę, że deklaracja zmiennej podobnie pozwala zarówno na „int stuff []”, jak i „int [] stuff”. Po prostu pozwalają, aby te same reguły działały dla deklaracji metod.
Brandon Yarbrough

2
@lImbus: Właściwie const T*i T const*są one równoważne, to właśnie T* conststanowi wskaźnik. Poza tym nienawidzę czcionek sans.
Simon Buchan,

3
W końcu numbers()[2]jest to oświadczenie prawne.
badp

184

INTERCAL jest prawdopodobnie najlepszym kompendium najdziwniejszych funkcji językowych. Moim osobistym faworytem jest instrukcja COMEFROM , która jest (prawie) przeciwieństwem GOTO.

COMEFROM jest mniej więcej przeciwieństwem GOTO, ponieważ może przenieść stan wykonania z dowolnego dowolnego punktu kodu do instrukcji COMEFROM. Punkt w kodzie, w którym następuje transfer stanu, jest zwykle podawany jako parametr parametru COMEFROM. To, czy transfer nastąpi przed instrukcją w określonym punkcie transferu, czy po niej, zależy od używanego języka. W zależności od używanego języka wiele obiektów COMEFROM odwołujących się do tego samego punktu wyjścia może być niepoprawnych, być niedeterministycznych, być wykonywanych z pewnego rodzaju określonym priorytetem, a nawet wywoływać wykonywanie równoległe lub w inny sposób równoległe, jak widać w wątku intercal. Prostym przykładem instrukcji „COMEFROM x” jest etykieta x (która nie musi znajdować się fizycznie w pobliżu odpowiedniego COMEFROM), która działa jak „drzwi pułapki”. Gdy wykonanie kodu osiągnie etykietę, kontrola jest przekazywana do instrukcji następującej po COMEFROM. Efektem tego jest przede wszystkim utrudnienie debugowania (i zrozumienia przepływu sterującego programu), ponieważ nie ma wskazań przy etykiecie, że sterowanie w tajemniczy sposób przeskoczy do innego punktu programu.


16
Całkiem złe - zamienia etykiety w GOTO. Wygląda na to, że hakerzy oferujący funkcje językowe błagają o ...
RCIX

114
Ok, ale INTERCAL ma być zabawny - nie jest to naprawdę zaskakująca „gotcha”. Kompilator INTERCAL może zrezygnować z kompilacji programu, jeśli nie używasz PLEASEmodyfikatora wystarczająco często!
Groo

10
Brzmi jak AOP :)
akuhn

6
Najbardziej mnie zadziwia to, że w analizie wymagań systemowych w „World of Commercial TI” COMEFROM są faktycznie używane w plikach tekstowych opisujących przypadki użycia. (poważnie: niektórzy analitycy tutaj opóźnili szeroką migrację korporacyjną do OpenOffice zamiast do MS Office, ponieważ ten pierwszy nie mógł poprawnie odnieść się do „comefrom” o wymaganej szczegółowości w łączu)
jsbueno

5
Groo: Gorzej. Używaj PLEASE zbyt często i odmawia kompilacji programu, ponieważ grasz w groveling (C-INTERCAL wymaga od 33% do 66% instrukcji, aby mieć modyfikatory PLEASE).
Vatine

160

Naprawdę nie jest to funkcja językowa, ale wada implementacji: Niektóre wczesne kompilatory Fortran zaimplementowały stałe za pomocą stałej puli. Wszystkie parametry zostały przekazane przez odniesienie. Jeśli wywołałeś funkcję, np

f(1)

Kompilator przekaże adres funkcji 1 w stałej puli do funkcji. Jeśli przypisałeś wartość do parametru w funkcji, zmieniłbyś wartość (w tym przypadku wartość 1) globalnie w programie. Spowodowało to drapanie głowy.


124
Och Wtedy 2+2 może być równy 5( 2oczywiście dla bardzo dużych wartości !).
Alok Singhal

12
hmm, jaka wartość 2 sprawiłaby, że „2 + 2” == „5”? Nie wiem, czy jakakolwiek wartość 2 może przyjąć wartość całkowitą.
Aaron

36
@earlz: Podejrzewam, że skończyłoby się jako integralna wartość, niezależnie od wzorca bitowego. Z drugiej strony, prawdopodobnie możesz ustawić w ten sposób od 5 do 4 (więc 2+2byłoby to równe 5dla małych wartości 5).
David Thornley,

18
Przepraszam, Alok, ale mówimy o wczesnym FORTRANIE. To nie będzie prawda 2 + 2 = 5; to będzie błąd składniowy. To, co będzie prawdą, jest 2 + 2 .EQ. 5.
David Thornley,

3
W Haskell następujący fragment ma wartość 5: „niech 2 + 2 = 5 w 2 + 2” :)
Tirpen

153

Nie wiem, czy można to uznać za funkcję języka, ale w C ++ prawie każdy błąd kompilatora związany z szablonami dostarcza sporo WTF do wielu programistów C ++ na całym świecie :)


15
W porządku, większość kodu związanego z szablonami już tworzy wiele WTF na całym świecie.
Joris Timmermans

43
Och, chodź teraz. niezdefiniowane odniesienie do `std :: basic_ostream <char, std :: char_traits <char>> & std :: operator << <std :: char_traits <char>> (std :: basic_ostream <char, std :: char_traits <char> > &, char const *) 'Jest doskonale czytelny!
Matt Greer

10
Kiedyś miałem błąd kompilatora związany z szablonami, który składał się z pięciu wierszy, z których najkrótszy miał siedemnaście tysięcy znaków (klasyczny błąd „brak dopasowania dla x”, w programie głęboko szablonowanym). To WTF, a nie przede wszystkim funkcja, szablony są wspaniałe.
Andrew McGregor,

111
Nawet jeśli nie ma błędu, spróbuj dowiedzieć się, które funkcje zajmują najdłużej swój profiler. Och, spójrz, tostd::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
Myślę, że to pasuje tutaj: sprawdź STLFilt na bdsoft.com/tools/stlfilt.html, aby odczyt był czytelny.
zapomniała

150

Wiele przestrzeni nazw C:

typedef int i;

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

Lub z postaciami:

typedef char c;

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

Jak do diabła to się jednoznacznie kompiluje !?
Earlz

13
Identyfikatory tagów +1 dla wyliczeń i struktur są najbardziej zagmatwaną częścią C imho. Niewiele osób rozumie, dlaczego idiom wpisywania wskaźnika do struktury wygląda tak jak on.
Tadeusz A. Kadłubowski

11
Kompiluje się, ponieważ każdy z nich ma jednoznaczną przestrzeń nazw ze względu na kontekst.
Andrew McGregor,

149

Powiedziałbym, że cała spacja w Pythonie jest moją największą funkcją WTF. To prawda, że ​​mniej więcej przyzwyczajasz się do tego po chwili, a nowoczesne edytory ułatwiają radzenie sobie z nim, ale nawet po przeważnie pełnoetatowym rozwoju Pythona w ubiegłym roku wciąż jestem przekonany, że to zły pomysł. Przeczytałem wszystkie uzasadnienia, ale szczerze mówiąc, przeszkadza to w mojej produktywności. Niewiele, ale wciąż jest zadzior pod siodłem.

edycja: sądząc po komentarzach, niektórzy ludzie myślą, że nie lubię wciskać mojego kodu. To błędna ocena. Zawsze wciskałem swój kod bez względu na język i to, czy jestem do tego zmuszony. Nie podoba mi się to, że to wcięcie określa, w którym bloku znajduje się wiersz kodu. Wolę do tego wyraźne ograniczniki. Między innymi uważam, że wyraźne ograniczniki ułatwiają wycinanie i wklejanie kodu.

Na przykład, jeśli mam blok z wcięciem 4 spacje i wklejam go na końcu bloku, który ma wcięcie 8 spacji, mój edytor (wszyscy redaktorzy?) Nie ma pojęcia, czy wklejony kod należy do bloku 8-spacji czy zewnętrznego blok. OTOH, jeśli mam wyraźne ograniczniki, oczywiste jest, do którego bloku należy kod i jak należy go (ponownie) wciąć - robi to inteligentnie szukając ograniczników bloków.

edycja 2: niektórzy ludzie, którzy komentują, wydają się sądzić, że jest to funkcja, której nienawidzę lub że sprawia, że ​​Python jest słabym językiem. Ponownie nieprawda. Chociaż nie lubię tego aż tak bardzo, to nie ma sensu. Pytanie dotyczy najdziwniejszej funkcji językowej i myślę, że jest to dziwne, ponieważ jest to coś bardzo, bardzo niewielu (ale> 0) języków.


63
jeśli przeszkadza to w produktywności, kod nie Pythona nie może być bardzo czytelny ...
Tor Valamo

27
Jakiego języka używałeś przed Pythonem? Jak mogłeś pracować z innymi ludźmi i nie wciskać tego języka? Jak ktokolwiek mógłby znosić kod bez wcięć w dowolnym języku? Czy pracowałeś w pokoju pełnym geniuszy, którzy nie potrzebowali wizualnych wskazówek w kodzie źródłowym?
S.Lott,

53
+1 Nie mogę zgodzić się więcej, jeśli mój edytor (Emacs) nie może automatycznie wciąć mojego kodu w oparciu o coś odrębnego (np. Nawiasy klamrowe / start, koniec / nazwij go) automatycznie, to naprawdę głupie. Prawie każde refaktoryzowanie, które wykonasz na „większej” funkcji, może być naprawdę złym doświadczeniem.
Dmitry

83
Oto oferta - w każdym innym języku mogę wyróżnić blok kodu i odpowiednio go wciąć w dowolnym edytorze. Ale ponieważ białe znaki są z definicji właściwym wcięciem, tracisz tę zdolność w Pythonie. Dlatego trudniej jest przenosić kod lub refaktoryzować rzeczy. A dla osoby, która twierdzi, że OP jest „pierwszą osobą, która twierdzi, że to problem”, musiałem przez pewien czas utrzymywać jakiś kod Pythona i teraz z tego powodu będę używać dowolnego języka zamiast Pythona.
Kendall Helmstetter Gelner

38
Nie mam nic przeciwko spacji w Pythonie. WTF polega na tym, że nie jest konsekwentnie egzekwowany. Możesz łączyć poziomy wcięć i tabulatory, o ile są one zgodne z rodzeństwem. Zatem pierwszy poziom wcięcia może być jedną spacją, a drugi może być dwiema tabulatorami, a to nie jest błąd składniowy.
ieure

138

Trochę o to walczyłem:

1;

W Perlu moduły muszą zwrócić coś prawdziwego .


29
Niektóre moduły mogą zwracać wartości na podstawie operacji wykonywalnych. Jeśli zawsze zwracasz
Anonimowy

8
Jeśli moja pamięć Perla służy mi poprawnie, zwracanie wartości true z modułu wskazuje, że moduł został pomyślnie załadowany. Zwrócenie fałszywej wartości oznaczało, że coś poszło nie tak i uniemożliwiłoby uruchomienie programu (jeśli nie zostanie złapany).
Barry Brown

Jest to również poprawna instrukcja C, tylko nic nie jest zwracane.
sigjuice

24
Mark Dominus napisał: „Bardzo rzadko używam, 'Cogito ergo sum';co, jak wszyscy wiedzą, jest oczywiste we wszystkich możliwych wszechświatach. Zapewnia to maksymalną przenośność”.
Greg Bacon

PHP <?=1;?>zwraca 1. <?=true;?>zwraca 1. <?=false;?>zwraca null.
Talvi Watia,

135

Dziwi mnie, że nikt nie wspominał o 7 konstrukcjach pętli 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

Ponieważ trzymanie! przed swoim warunkowym sposób zbyt skomplikowane!


47
Powinni byli to zrobić „ Whilei Whend”, ponieważ są ludzie, którzy wymawiają słowo „podczas” z bezdźwięcznym labializowanym przybliżeniem welarowym. I oczywiście ładniej się układa, a kod, który się układa jest fajny.
dreamlax

43
Dlaczego zachowujesz się tak dziwnie?
Erik Forbes,

48
Łał. Kiedy się nad tym zastanawiam, robi mi się trochę nostalgicznie. Pierwszy raz, kiedy użyłem VB, wróciłem jako 9-latek. Pochodzę ze Szwecji i nie byłem wtedy zbyt biegły w języku angielskim. Istnieje szwedzkie słowo o nazwie „vänd”, które w zasadzie oznacza „zawrócić” i jest wymawiane podobnie jak „wend”. Z tego powodu myślałem, że to ma sens ... :)
Emil H

61
! nie ma go w VB, to „nie”. Albo to jest? Tak, nie jest, ale nie.
brianary

7
Tak, „Wend” to angielskie słowo, które oznacza iść lub kontynuować jakiś kurs lub drogę ( google.com/search?q=define%3A+wend ). Nie jestem pewien, czy to pomaga, czy boli.
Michael Myers

134

Dla tych, którzy nie wiedzą, bcjest „językiem kalkulatora o dowolnej precyzji” i używam go dość często do szybkich obliczeń, szczególnie gdy liczby są duże ( $pojawia się monit):

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

bcjest standardowym poleceniem uniksowym .

Teraz „funkcja WTF”. To jest z man bc(moje podkreślenie):

quit : Po odczytaniu instrukcji quit procesor bc zostaje zakończony, niezależnie od tego, gdzie znajduje się instrukcja quit. Na przykład „if (0 == 1) quit” spowoduje zakończenie działania bc.

halt : Instrukcja halt (rozszerzenie) jest wykonywaną instrukcją, która powoduje, że procesor bc kończy pracę tylko wtedy, gdy jest wykonywany. Na przykład „if (0 == 1) halt” nie spowoduje zakończenia bc, ponieważ zatrzymanie nie jest wykonane.


41
Używam do tego Haskell.
Thomas Eding

8
Kalkulator Google?
igul222

7
Sam zacząłem używać Pythona, a kalkulator Google jest fajny, jeśli jesteś online. Ale kiedyś tego używałem bci chciałem pisać o tym bcw moim poście ze względu na świetne cytaty ze strony man.
Alok Singhal

6
@Brian, to ci się spodoba: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc(chociaż możesz już to wiedzieć).
Alok Singhal

2
Używam irb (interaktywna powłoka Ruby). Ale w tamtych czasach zawsze sięgałem po dc - jak bc, ale używa odwrotnego polerowania. Geektastic!
tragomaskhalos

134

Zawsze zastanawiałem się, dlaczego najprostszym programem było:

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

Może to być:

print "Hello World!"

Może przede wszystkim to przeraża studentów informatyki ...


34
W niektórych językach „Hello World!” jest prawidłowym programem.
David Thornley,

31
@SoMoS: w najbardziej dynamicznych językach, takich jak Python, Ruby lub Perl, drukuje „Hello World!” lub niektóre drobne zmiany (np. puts zamiast print) to prawidłowy i kompletny program.
Dave Kirby,

36
@Loadmaster: implikacja była taka, że ​​„cały kod należy do klasy” lub „cały kod należy do funkcji” są niepotrzebnymi ograniczeniami
Jimmy

19
Tylko dlatego, że język wymusza użycie obiektów, nie oznacza, że ​​jest używany do właściwego programowania obiektowego. Programowanie proceduralne w Javie lub C # jest całkowicie możliwe. Do tego służą metody statyczne.
jdmichal

68
Uwielbiam ludzi, którzy myślą, że OOP oznacza, że ​​wszystko powinno być przedmiotem.
Tor Valamo

132

JavaScript jest zorientowany obiektowo, prawda? Dlatego uruchamianie metod na literalnych ciągach i liczbach powinno działać. Lubię "hello".toUpperCase()i 3.toString(). Okazuje się, że drugi to błąd składniowy, dlaczego? Ponieważ analizator oczekuje, że liczba, po której następuje kropka, będzie literałem zmiennoprzecinkowym. To nie jest WTF, WTF polega na tym, że musisz tylko dodać kolejną kropkę, aby działało:

3..toString()

Powodem jest to, że dosłowność 3.jest interpretowana jako 3.0i 3.0.toString()działa dobrze.


8
Działa w ten sposób również w Pythonie (spróbuj 3..__add__(4)). Z drugiej strony uważam, że (3).__add__(4)jest to sposób na znacznie mniej uszkodzony mózg :)
badp

49
Możesz po prostu zrobić (3) .toString ()
Joseph Montanez

13
@ Gorilla3D: tak, ale to nie jest dziwna funkcja językowa, prawda?
Theo

25
3.0.toString()swędzi mnie oczy.
Ben Blank

18
127.0.0.1.toInt ()
berkus

130

W JavaScript:

2 == [2]

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

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

Na szczęście mili ludzie ze stackoverflow.com wyjaśniali mi wszystko: dlaczego 2 == [2] w JavaScript?


6
Dlatego powinieneś użyć ===zamiast tego.
Gumbo,

10
Jest to przydatne, jeśli masz funkcję, która zwraca liczbę i chcesz zwrócić z nią dodatkowe metadane, możesz zwrócić [liczba] z dodanymi dodatkowymi polami. Prosty kod nigdy się nie dowie, że nie jest liczbą rzeczywistą, a inny kod może uzyskać wymagane metadane.
Andrey Shchekin

36
@Andrey, z wyjątkiem tego, że jeśli będę musiał zachować kod, który robi to, co sugerujesz, bardzo szybko życzyłbym śmierci autorowi.
Breton

@Andrey, to świetny pomysł! Możesz także użyć Number(n)do zrobienia czegoś podobnego. Niestety w obu naszych rozwiązaniach ===przerwy = (.
Xavi


126

Moją największą nienawidzoną funkcją jest dowolna składnia pliku konfiguracyjnego, która zawiera logikę warunkową. Tego rodzaju rzeczy są powszechne w świecie Java (Ant, Maven itp. Wiesz, kim jesteś!).

Po prostu kończysz programowanie w języku ac ** p, z ograniczonym debugowaniem i ograniczoną obsługą edytora.

Jeśli potrzebujesz logiki w swojej konfiguracji, podejście w języku Python do kodowania konfiguracji w prawdziwym języku jest znacznie lepsze.


24
Tcl wynalazł to na długo przed narodzinami Pythona, a Lisp wynalazł je wcześniej. Więc nie nazywajmy go Pythonic, nazwijmy to Emacs-ish.
slebetman

46
Nazwijmy to dobrze.
mletterle

30
AMEN. Jeśli konfiguracja lub język kompilacji jest w toku, oznacza to, że robisz to źle. Patrzę na ciebie CMake / autotools.
Joseph Garvin

16
Właśnie do tego właśnie została zaprojektowana Lua
Cogwheel

1
Cóż, jeśli kod znajduje się w Pythonie, to plik konfiguracyjny powinien być świetnym pomysłem, ponieważ wystarczy zaimportować plik i odczytać atrybuty modułu. W pliku konfiguracyjnym otrzymujesz 100% mocy Turing Complete Pythona.
asmeurer 14.01.11

113

powerbasic (www.powerbasic.com) zawiera dyrektywę kompilatora:

# BLOAT {bloatsize}

zwiększa to rozmiar skompilowanego pliku wykonywalnego o <bloatsize>bajty. zostało to umieszczone w kompilatorze na wypadek, gdyby ludzie tworzący plik wykonywalny nie lubili niewielkiego rozmiaru generowanego pliku wykonywalnego. sprawia, że ​​EXE wydaje się większy, aby konkurować z rozdętymi językami programowania :)


9
Haha fuj. Słyszałem o programistach celowo spowalniających niektóre operacje (np. Wyszukiwanie), ponieważ pomaga to ludziom wierzyć, że naprawdę coś robi. Podejrzewam, że podobna rzecz.
David

42
To przypomina mi coś, co ostatnio czytałem. Testowali FPS i postanowili zwiększyć liczbę punktów wytrzymałości złych facetów. Następnie zapytali testerów, jaka jest sztuczna inteligencja, i przyrzekli, że jest to znacznie mądrzejsze. Ale AI się nie zmieniło, tylko punkty wytrzymałości. Ludzie mają w głowie pewną narrację o świecie, a jeśli zrozumiesz i spełnisz ich oczekiwania, po prostu założą, że potwierdza ich narrację.
Nate CK

5
Dodawałem do programów dodatkowe spowolnienie, aby wyglądały, jakby robiły coś skomplikowanego. To znaczy z powrotem w szkole podstawowej.
Matti Virkkunen

3
W szkole mieliśmy 80286 maszyn i musiałem napisać kilka procedur wyjścia ekranu w asemblerze, aby uzyskać rozsądną prędkość (tj. Nie czołganie się).
berkus

7
@Nate CK, jeśli AI żyje dostatecznie długo, aby pokazać swoją AI, to może faktycznie być mądrzejszy, a zanim to mogło zbyt szybko umarł, aby to udowodnić.
zzzzBov
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.