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ź.
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ź.
Odpowiedzi:
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.
W JavaScript:
'5' + 3 gives '53'
Natomiast
'5' - 3 gives 2
+
bo łączenie strun jest okropne
W JavaScript następująca konstrukcja
return
{
id : 1234,
title : 'Tony the Pony'
};
return jest błędem składniowym wynikającym z podstępnego niejawnego wstawiania średnika w nowej linii po undefined
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;
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
==
służy w oczach projektanta języka?
==
miał znaczenie ===
, a wtedy byłby inny operator, coś takiego ~=
pozwalało na przymus typu.
Trigrafie w C i C ++.
int main() {
printf("LOL??!");
}
Spowoduje to wydrukowanie LOL|
, ponieważ kaligraf ??!
jest konwertowany na |
.
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
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 127
chyba, ż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;
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;
}
Control cannot leave the body of a finally clause
return
w finally
klauzuli.
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
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) );
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 PerlaTam jest o wiele więcej. Przeczytaj pełną listę tutaj .
$[
Zmienna jest najbardziej zło z nich wszystkich.
perldoc perlvar
co 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)
use English;
polega na tym, że wpływa to na wydajność RegExp. Nie wymyślam tego. perldoc.perl.org/English.html#PERFORMANCE
/$foo[bar]/
, jest [bar]
częścią klasy znak lub indeks do tablicy @foo
? Grep perldata za przerażającą odpowiedź.
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.
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
( IF
jest zmienną THEN
i ELSE
są podprogramami)
„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 .
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);
}
}
while
na końcu jest (warunkowy) JMP
powrót do do
, co wyjaśnia, dlaczego możesz pominąć do
i nadal kończyć w pętli.
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]);
}
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]; } }); }
?
W Pythonie:
>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
Nie WTF, ale przydatna funkcja.
(10 > 5 > 1) != ((10 > 5) > 1)
w Pythonie.
(funct_a(5)+5 > b > funct_a(5))
dzwoni tylko funct_a(5)
raz. To WIELKA funkcja!
funct_a
w tym przykładzie zostanie wywołany dwukrotnie. W b > funct_a(5) > c
zostanie wywołana tylko raz, choć w przeciwieństwie do b > funct_a(5) and funct_a(5) > c
.
W Javie:
int[] numbers() {
return null;
}
Można zapisać jako:
int numbers() [] {
return null;
}
const T*
i T const*
są one równoważne, to właśnie T* const
stanowi wskaźnik. Poza tym nienawidzę czcionek sans.
numbers()[2]
jest to oświadczenie prawne.
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.
PLEASE
modyfikatora wystarczająco często!
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.
2+2
może być równy 5
( 2
oczywiście dla bardzo dużych wartości !).
2+2
byłoby to równe 5
dla małych wartości 5
).
2 + 2 = 5
; to będzie błąd składniowy. To, co będzie prawdą, jest 2 + 2 .EQ. 5
.
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 :)
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> >)
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);
}
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.
Trochę o to walczyłem:
1;
W Perlu moduły muszą zwrócić coś prawdziwego .
'Cogito ergo sum';
co, jak wszyscy wiedzą, jest oczywiste we wszystkich możliwych wszechświatach. Zapewnia to maksymalną przenośność”.
<?=1;?>
zwraca 1. <?=true;?>
zwraca 1. <?=false;?>
zwraca null.
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!
While
i 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.
Dla tych, którzy nie wiedzą, bc
jest „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
bc
jest 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.
bc
i chciałem pisać o tym bc
w moim poście ze względu na świetne cytaty ze strony man.
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
(chociaż możesz już to wiedzieć).
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 ...
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.0
i 3.0.toString()
działa dobrze.
3..__add__(4)
). Z drugiej strony uważam, że (3).__add__(4)
jest to sposób na znacznie mniej uszkodzony mózg :)
3.0.toString()
swędzi mnie oczy.
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?
===
zamiast tego.
Number(n)
do zrobienia czegoś podobnego. Niestety w obu naszych rozwiązaniach ===
przerwy = (.
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.
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 :)