Fitur bahasa yang aneh

974

Apa, menurut Anda, fitur bahasa yang paling mengejutkan, aneh, aneh atau benar-benar "WTF" yang Anda temui?

Harap hanya satu fitur per jawaban.

Robert Harvey
sumber
5
@ gablin Saya pikir jika Anda menggabungkan pembatas LISP dengan PERL regex menggunakan penguraian javascript, Anda akan mencakup 90% dari WTF ...
Talvi Watia

Jawaban:

1859

Di C, array dapat diindeks seperti:

a[10]

yang sangat umum.

Namun, bentuk yang kurang dikenal (yang benar-benar berfungsi!) Adalah:

10[a]

yang artinya sama dengan di atas.

Edan Maor
sumber
758
itu karena [10] berarti * (a + 10) ... dan 10 [a] berarti * (10 + a) :)
Michel Gokan
77
Jangan lupa "Hello World" [i]. Atau saya ["Hello World"]
Richard Pennington
167
Atau, lebih bermanfaat, "0123456789abcdef" [x & 0xf]
Dipstick
17
@ frunsi: Selalu berfungsi seperti yang diharapkan. Penambahan pointer tidak sama dengan penambahan integer sederhana pada alamat. Itu komutatif tidak peduli apa ukuran adalah jenis yang dimaksud.
R. Martinho Fernandes
12
@ mcv - a [10] sama dengan "* (a + 10)", di mana ungkapan "a + 10" adalah aritmatika penunjuk (dan karena a adalah pendek, dalam contoh Anda, a + 10 berarti 'mulai dari alamat a, dan pindahkan 10 celana pendek, yaitu 20 byte '). Ekspresi 10 [a] diinterpretasikan sebagai "* (10 + a)", di mana "10 + a" juga merupakan aritmatika penunjuk, dan diperlakukan dengan cara yang persis sama.
Edan Maor
1292

Dalam JavaScript:

 '5' + 3 gives '53'

Sedangkan

 '5' - 3 gives 2
Dipstick
sumber
81
Saya ingat ketika saya pertama kali mulai menggunakan javascript menggunakan teknik semacam ini untuk menambahkan angka dalam string: "111" - - "222" memberi 333 sedangkan "111" + "222" memberi "111222".
Callum Rogers
112
+untuk rangkaian senar itu mengerikan
Matteo Riva
416
+ untuk konser bukan masalah. Mengetik lemah adalah.
FogleBird
270
@FogleBird Tidak ada yang benar-benar masalah. Hanya kombinasi keduanya dengan aturan paksaan yang tidak konsisten.
TM.
70
Jadi pada dasarnya, + cocok ketika sebuah string terlibat. Mengapa mereka tidak bisa membuat kode seperti '123456' - 456 = '123'? Itu akan menarik.
Jimmie Lin
872

Dalam JavaScript, konstruk berikut

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

kembaliundefined adalah kesalahan sintaksis karena penyisipan titik koma implisit licik pada baris baru setelah return. Berikut ini berfungsi seperti yang Anda harapkan:

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

Lebih buruk lagi, ini juga berfungsi (setidaknya di Chrome):

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

Berikut adalah varian dari masalah yang sama yang tidak menghasilkan kesalahan sintaksis, hanya gagal secara diam-diam:

return
    2 + 2;
DrJokepu
sumber
225
Penyisipan titik koma adalah salah satu bagian paling jahat dari JavaScript.
230
Anda selalu mengalami masalah ketika Anda merancang fitur bahasa di sekitar asumsi bahwa pengguna Anda sebagian besar akan menjadi idiot.
Rob Van Dam
8
Saya benar-benar memiliki masalah itu, karena c # developer sendiri, saya meletakkan brace di baris baru. Butuh waktu berjam-jam untuk menyadari apa masalahnya. Bahkan ketika saya telah memecahkan masalah, saya tidak tahu apa masalahnya sampai saya membaca jawaban Anda!
Fedor Hajdu
24
Nick Retallack: Karena, karena sintaks kurung & tanda titik koma JavaScript-C JavaScript, tidak jelas sama sekali bahwa baris baru signifikan.
Tamas Czinege
19
Jika Anda tidak seharusnya menggunakan gaya C saat pemrograman dalam JavaScript, maka itu agak menyimpang dari desainer bahasa JavaScript untuk memilih sintaks gaya C.
Ryan Lundy
795

Tabel kebenaran 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

Sumber: Doug Crockford

Chandra Patni
sumber
237
Untung Javascript memiliki operator ===.
Anonim
65
Jadi, tujuan apa yang ada ==di mata perancang bahasa?
Chris S
137
Orang membingungkan.
Javier
123
Akan lebih baik jika ==memiliki arti ===, dan kemudian ada operator lain, sesuatu seperti ~=itu memungkinkan pemaksaan tipe.
TM.
18
@ Otto Sebenarnya, karena kita geeking keluar, contohnya menunjukkan bahwa == tidak simetris. Saat ini, saya tidak melihat bagaimana komutatif akan ditentukan untuk hubungan biner.
PeterAllenWebb
660

Trigraph dalam C dan C ++.

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

Ini akan dicetak LOL|, karena trigraph ??!dikonversi menjadi |.

Andreas Bonini
sumber
71
Cepat! Beri tahu semua C / b / programmer!
Esteban Küber
235
Trigraph luar biasa, karena Anda dapat yakin tidak ada yang akan -ever- mencari tahu apa ??! akan berarti dari Google tanpa mengetahui namanya.
zaratustra
56
Trigraph dinonaktifkan secara default di GCC.
sastanin
360
Ini memungkinkan Anda menggunakan "operator WTF": (foo ()! = ERROR) ??! ??! cerr << "Terjadi kesalahan" << endl;
user168715
57
Trigraph adalah kejahatan yang perlu saat diperkenalkan. Beberapa platform tidak menyertakan kunci karakter tertentu ke bahasa, jadi itu adalah "trigraph" atau "Anda tidak dapat memiliki kompiler C akhir periode pernyataan akhir jadi gunakan assembler". Lihat deskripsi Stroustrup di "Bahasa Pemrograman C ++".
Euro Micelli
573

Bersenang-senang dengan tinju otomatis dan cache integer di Jawa:

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

Penjelasan

Intip sekilas kode sumber Java akan muncul sebagai berikut:

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

Catatan: IntegerCache.high default ke 127kecuali ditentukan oleh properti.

Apa yang terjadi dengan tinju otomatis adalah bahwa baik foo dan bar objek integer yang sama diambil dari cache kecuali dibuat secara eksplisit: misalnya foo = new Integer(42), sehingga ketika membandingkan persamaan referensi, mereka akan benar daripada salah. Cara yang tepat untuk membandingkan nilai Integer adalah menggunakan.equals;

yx.
sumber
31
Butuh saya beberapa detik untuk melihat mengapa ... java harus menyimpan kumpulan instance Integer untuk nilai antara -128 dan 128, jika tidak maka akan membagikan Integer baru, bukan?
Mike Akers
18
namun perlu diingat bahwa jika Anda menetapkan Integer baru (42) itu tidak akan menggunakan instance dari pool sehingga foo == bar akan dievaluasi menjadi false
z -
10
Saya selalu menggunakan int bukan Bilangan bulat jika memungkinkan, tetapi jika saya harus menggunakan Bilangan Bulat untuk beberapa alasan, haruskah saya menggunakan .equals () alih-alih ==?
MatrixFrog
246
Senang sekali saya seorang programmer C #.
87
@ Akan: C # memiliki beberapa gotcha yang sangat mirip. Lihat blogs.msdn.com/jmstall/archive/2005/03/06/386064.aspx
spookylukey
373

Mengutip Neil Fraser (lihat bagian akhir halaman itu),

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

(di Jawa, tetapi perilaku tampaknya sama dalam JavaScript dan Python). Hasilnya dibiarkan sebagai latihan untuk pembaca.

Diedit: Selama kita membahas hal ini pertimbangkan juga ini:

try {
    throw new AssertionError();
} finally {
    return false;
}
lorenzog
sumber
42
+1. Untuk beberapa alasan, saya menemukan ini lucu dan tidak bisa berhenti tertawa.
outis
153
Syukurlah C # tidak memungkinkan kegilaan seperti itu ...Control cannot leave the body of a finally clause
Richard Ev
64
Ini mengembalikan, salah, bukan? Ini mungkin terlihat seperti WTF (dan mungkin itu salah satunya), tapi saya hidup dengan aturan: Akhirnya selalu menang, kecuali Anda menabrak Mesin sebelumnya.
Michael Stum
28
Agar adil, saya menyalahkan penjelasan bagus TDWTF karena mengingat bahwa akhirnya selalu menang kecuali Anda mencabut kabel listrik: thedailywtf.com/Articles/My-Tales.aspx
Michael Stum
22
Saya tidak yakin kode apa yang harus dikembalikan dalam kasus ini. Tapi aku benar-benar yakin bahwa Anda tidak harus menempatkan returndi finallyklausa.
jfs
325

APL (selain SEMUA itu), kemampuan untuk menulis program apa pun hanya dalam satu baris.

mis . Permainan Kehidupan Conway dalam satu baris dalam APL :

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

Jika garis itu bukan WTF, maka tidak ada apa-apa!

Dan ini sebuah video

lkessler
sumber
19
Saya suka APL. Ah, kegembiraan menghabiskan sepanjang sore untuk menulis setengah baris kode! Hal pertama yang akan saya lakukan ketika saya mendapatkan keyboard di mana saya dapat memprogram huruf apa yang ditampilkan adalah untuk kembali berkenalan dengan APL.
Daniel C. Sobral
24
Sepertinya bahasa untuk orang Yunani.
Esko
45
@Erik: Ada kegembiraan ditemukan dalam menulis kode yang hanya tentang apa yang Anda inginkan, dan bukan tentang bagaimana menuju ke sana. Mengekspresikan kode Anda sebagai satu ekspresi. Ini seperti potongan katana sempurna yang sempurna. Tentu saja, dalam pertarungan sungguhan aku lebih suka punya senjata.
Daniel C. Sobral
7
@Aniel: Anda menghabiskan sepanjang sore untuk menulis satu baris kode ... dan satu minggu penuh untuk membaca satu baris kode. ;-)
Jürgen A. Erhard
93
APL akan luar biasa untuk ditonton dalam film aksi fiksi ilmiah. Saya bisa membayangkan seseorang duduk di terminal tiga warna bergumam, "Membentuk kembali vektor rudal musuh ... transpos ... pi kali logaritma ... naik kelas - dan - jalankan!" diikuti oleh ledakan dan sorak-sorai.
Joey Adams
321

Hal-hal aneh yang dapat digunakan templat C ++, paling baik ditunjukkan oleh "Literal Analog Multi-Dimensi" yang menggunakan templat untuk menghitung area bentuk "digambar". Kode berikut ini valid C ++ untuk persegi panjang 3x3

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

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

Atau, contoh lain dengan kubus 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
sumber
18
Sementara literal analog Eelis hebat, apakah mereka fitur bahasa yang aneh , atau hanya cara yang aneh untuk menggunakan fitur?
85
WTF nyata akan menjadi kesalahan kompiler yang dihasilkan oleh salah satu dari mereka yang cacat.
Andrew McGregor
6
Betapa sakitnya itu .. membangunkan saya lagi ketika ada versi AnalogLiterals yang mendukung memutar literal di sekitar sumbu X, Y dan Z di Eclipse ... sekarang yang akan memberikan "pemrograman visual" makna nyata yang baru.
TheBlastOne
2
Apakah pemesanan masalah o dan L dan |?
Ming-Tang
4
Urutan pemesanan penting, karena templat membuat penggunaan kreatif berlebihan operator. (Jangan lakukan ini dengan kode asli, operator yang menyalahgunakan membuat kode sulit dibaca)
josefx
292

Banyak variabel bawaan Perl:

  • $#- bukan komentar!
  • $0,, $$dan $?- sama seperti variabel shell dengan nama yang sama
  • ,, $&dan $'- variabel pencocokan aneh
  • $"dan $,- variabel aneh untuk pemisah daftar dan keluaran-bidang
  • $!- Seperti errnosebagai angka tetapi strerror(errno)sebagai string
  • $_- yang variabel siluman, selalu digunakan dan tidak pernah terlihat
  • $#_ - nomor indeks argumen subrutin terakhir ... mungkin
  • @_ - nama (bukan) dari fungsi saat ini ... mungkin
  • $@ - pengecualian terakhir
  • %:: - tabel simbol
  • $:, $^, $~, $-, Dan $=- ada hubungannya dengan format output
  • $.dan $%- masukan nomor baris, nomor halaman keluaran
  • $/dan $\- pemisah rekaman input dan output
  • $| - Pengontrol buffering keluaran
  • $[- ubah basis array Anda dari berbasis 0 ke berbasis 1 menjadi berbasis 42: WHEEE!
  • $}- tidak ada sama sekali, anehnya!
  • $<, $>, $(, $)- UID yang nyata dan efektif dan Gids
  • @ISA - nama superclasses langsung paket saat ini
  • $^T - waktu mulai skrip dalam beberapa detik
  • $^O - nama sistem operasi saat ini
  • $^V - versi Perl ini apa

Ada lebih banyak dari mana mereka berasal. Baca daftar selengkapnya di sini .

Chris S
sumber
83
The $[variabel kejahatan sebagian besar dari mereka semua.
Brad Gilbert
24
Pasti akan menghargai jika Perl 6 adalah sesuatu yang saya dapat kode tanpa harus memeriksa perldoc perlvarsetiap lima detik. (Meskipun saya mengakui bahwa separuh waktu saya mengeceknya dengan berpikir "Saya tahu ada variabel khusus yang dapat melakukan ini untuk saya, saya hanya tidak ingat yang mana ..." = P)
Chris Lutz
17
Masalahnya use English;adalah itu mempengaruhi kinerja RegExp. Saya tidak mengada-ada. perldoc.perl.org/English.html#PERFORMANCE
Dave Webb
13
@Dave: ini bukan masalah karena opsi -no_match_vars di halaman yang Anda tautkan. @Brad: $ [SANGAT jahat. Niat di balik itu jahat, ya, tapi itu juga tidak berhasil! @Artem: from perlvar "Identifier perl yang dimulai dengan angka, karakter kontrol, atau karakter tanda baca dikecualikan dari efek deklarasi paket dan selalu dipaksa berada di paket utama; mereka juga dibebaskan dari kesalahan 'vars' yang ketat." Jadi itu berarti @ $ akan dibuat dan ditugaskan tanpa kesalahan bahkan di bawah striktur. Ugh!
rjh
4
@Brian: Bagaimana Anda mengusulkan untuk mempelajari sintaks ketika dokumentasi resmi itu sendiri menyatakan bahwa ada keadaan di mana penerjemah Perl heuristically menebak apa arti urutan karakter? Misalnya dalam /$foo[bar]/, apakah [bar]bagian kelas karakter atau subskrip ke array @foo? Grep perldata untuk jawaban yang menakutkan.
j_random_hacker
289

PHP menangani nilai numerik dalam string . Lihat jawaban sebelumnya untuk pertanyaan berbeda untuk perincian lengkap tetapi, singkatnya:

"01a4" != "001a4"

Jika Anda memiliki dua string yang berisi jumlah karakter berbeda, mereka tidak dapat dianggap sama. Angka nol di depan penting karena ini adalah string bukan angka.

"01e4" == "001e4"

PHP tidak suka string. Ia mencari alasan apa pun yang dapat ditemukan untuk memperlakukan nilai Anda sebagai angka. Ubah sedikit karakter heksadesimal dalam string itu dan tiba-tiba PHP memutuskan bahwa ini bukan string lagi, mereka adalah angka dalam notasi ilmiah (PHP tidak peduli bahwa Anda menggunakan tanda kutip) dan mereka setara karena nol terkemuka diabaikan untuk angka. Untuk memperkuat poin ini Anda akan menemukan bahwa PHP juga mengevaluasi "01e4" == "10000"sebagai true karena ini adalah angka dengan nilai yang setara. Ini perilaku yang terdokumentasi, hanya saja tidak terlalu masuk akal.

Dan Dyer
sumber
56
Cukup gunakan === dan! ==. Yang harus tetap digunakan kecuali perbandingan jenis longgar diperlukan.
Dykam
14
@Dykam, jika Anda mengikuti tautan ke jawaban yang lebih lengkap, Anda akan melihat bahwa saya telah membahas penggunaan operator ===.
Dan Dyer
18
Lemah mengetik serangan lagi!
gillonba
43
Saya selalu tahu PHP adalah dosa. Sampai sekarang saya tidak menyadari bahwa itu adalah dosa yang tidak termaafkan: D
Thomas Eding
2
Mereka harus membuat orang menggunakan === dalam buku pemrograman atau tutorial apa pun. Catatan tambahan: Pada aplikasi PHP yang ditulis dengan buruk, saya dapat menyediakan apa pun kata sandi saya yang diuraikan sebagai nomor yang sama.
Pepijn
282

Mari kita pilih semua bahasa (seperti PL / I) yang mencoba menghilangkan kata-kata yang dipesan.

Di mana lagi Anda bisa menulis ekspresi lucu seperti:

IF IF THEN THEN = ELSE ELSE ELSE = THEN

( IF, THEN, ELSEAdalah nama-nama variabel)

atau

IF IF THEN THEN ELSE ELSE

( IFadalah variabel, THENdan ELSEmerupakan subrutin)

MZB
sumber
1
@quark: itu jawaban terpisah untuk ini! ;) ... (dan ya, Anda dapat memprogram dengan bahasa Inggris, cukup sebarkan sebagai .ppt ke pengembang lain.;)
Macke
28
@RoadieRich satu kelompok kerbau tidak secara eksplisit dari Kerbau, mereka hanya kerbau biasa saja.
Jürgen A. Erhard
18
John tempat James pernah memiliki memiliki memiliki efek yang lebih baik pada guru.
GameFreak
4
Saya melihat beberapa pembuat tanda di luar pabrik pabrik es krim Ben dan jerik kemarin. Saya mengkritik pekerjaan mereka, saya memberi tahu mereka bahwa tidak ada cukup ruang antara ben dan dan dan dan dan jerigen.
Tom Gullen
9
Mungkin itu akan dibutuhkan untuk program temporal di masa depan. JIKA KEMUDIAN = SEKARANG & & DIMANA = DI SINI KEMUDIAN KEMUDIAN = KEMUDIAN LAIN SEKARANG = DI TEMPAT LAIN
Kelly S. French
282

'Fitur' konversi oktal JavaScript bagus untuk diketahui:

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

Lebih detail di sini .

Brian Deterling
sumber
60
Terjebak di bug yang semua angka berfungsi kecuali 8 dan 9 !! Gila !!! Brian terima kasih!
Faruz
10
@Ya. Bukankah maksudmu oktal? Heksadesimal adalah 0x.
Luiscubal
48
Dan itu sebabnya parseInt mengambil argumen ekstra (opsional) :).
LiraNuna
10
memimpin 0 berarti angka oktal. karena 8 bukan digit oktal yang valid, hasilnya harus 0.
devio
22
... dan parseInt ('010') -> 8 hanya untuk membingungkan Anda.
Richard Gadsden
213

Perangkat Duff di C!

Dalam C satu dapat mengaitkan do / while dengan pernyataan switch. Berikut ini contoh memcpy menggunakan metode ini:

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
sumber
9
Perangkat Duff mungkin merupakan alasan yang baik untuk pernyataan switch tidak memiliki jeda secara default ;-) Namun, saya belum melihat penggunaan lain yang baik dari switch dan loop interlaced - tetapi mungkin ada satu. Oh, tunggu, ya, ada kegunaan lain: coroutine dan protothreads.
Frunsi
16
@ frunsi: "Perangkat Duff mungkin merupakan alasan yang baik untuk pernyataan beralih tidak memiliki istirahat secara default" - Selalu menjadikan kasus umum sebagai default. Saya tidak akan mengatakan ini adalah kasus umum ..
BlueRaja - Danny Pflughoeft
6
@ mcv mungkin paling mudah jika Anda mencoba untuk membacanya sebagai kode assembly, yaitu whiledi bagian akhir adalah (bersyarat) JMPkembali ke do, yang menjelaskan mengapa Anda dapat melewatkan dodan masih berakhir di loop.
wds
14
Perlu diingat bahwa Duff's Device umumnya menghasilkan kode WORSE daripada pernyataan perulangan normal untuk kompiler modern, yang tahu bagaimana (lebih baik) lilitan membuka gulungan daripada yang dapat Anda lakukan dengan tangan.
Billy ONeal
37
@ frunsi: Duff sendiri, menerbitkannya, mengklaim sesuatu seperti ini: "Ini pasti memberikan argumen dalam diskusi apakah peralihan harus gagal secara default, tapi saya tidak yakin apakah argumen itu mendukung atau menentangnya."
SF.
204

Algol lulus dengan nama (diilustrasikan menggunakan sintaks 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
sumber
33
Jika Anda berpikir tentang hal itu, itu benar-benar masuk akal
RCIX
90
Ini adalah "referensi referensi" tertinggi.
Dykam
3
Mungkin saja dalam Scala ( def f(j : => int))
Dario
10
Jadi ini seperti apa ... 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
Ini sebenarnya sangat mudah: Anda menghasilkan sepotong kecil kode (biasanya disebut "thunk", maka permainan kata-kata saya di atas) yang menghitung alamat yang dihasilkan dari ekspresi, dalam hal ini & a [i]. Penunjuk ke fungsi ini diteruskan ke fungsi yang dipanggil, yang kemudian menggunakannya untuk menghitung alamat saat ini setiap kali parameter diakses.
Richard Pennington
189

Dengan Python:

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

Bukan WTF, tetapi fitur yang bermanfaat.

MAK
sumber
176
Saya berharap setiap bahasa lain memiliki fitur ini
vava
32
Seperti dengan hampir semua fitur Python keren, sepertinya Guido hanya ALGOL-ized sintaks fitur Lisp keren. :-)
Ken
4
Geoffrey, ini adalah fitur, dan (10 > 5 > 1) != ((10 > 5) > 1)dalam Python.
sastanin
18
Juga, ini hanya mengevaluasi sekali, jadi (funct_a(5)+5 > b > funct_a(5))hanya memanggil funct_a(5)sekali. Ini adalah fitur HEBAT!
Khelben
57
@Khelben: Tidak, funct_aakan dipanggil dua kali dalam contoh itu. Di b > funct_a(5) > cdalamnya hanya akan dipanggil sekali, sebagai lawan b > funct_a(5) and funct_a(5) > c.
Baffe Boyois
189

Di Jawa:

int[] numbers() {
  return null;
}

Dapat ditulis sebagai:

int numbers() [] {
  return null;
}
Chandra Patni
sumber
23
Wow! Saya berharap saya bisa menjadi lalat di dinding ketika sintaks array itu dirancang!
Adam Paynter
29
Saya benci mengatakan ini tetapi WTF adalah ekstensi yang konsisten dari sistem tipe C. Jika fungsi C diizinkan untuk mengembalikan array maka seperti itulah tampilannya. Yang lebih bagus adalah pelanggaran konsistensi untuk membuatnya lebih mudah dibaca. Mirip seperti "const char * var" vs "char const * var".
Gordon Wrigley
15
@ Adam - Sebenarnya masuk akal bila Anda menganggap bahwa deklarasi variabel juga memungkinkan "hal int []" dan "int [] hal". Mereka hanya membiarkan aturan yang sama bekerja untuk deklarasi metode.
Brandon Yarbrough
2
@ lImbus: Sebenarnya, const T*dan T const*setara, itu T* constyang mengarahkan pointer. Juga, saya benci font sans.
Simon Buchan
3
Lagipula, itu numbers()[2]adalah pernyataan hukum.
badp
184

INTERCAL mungkin adalah ringkasan terbaik dari fitur bahasa yang paling aneh. Favorit pribadi saya adalah pernyataan COMEFROM yang (hampir) kebalikan dari GOTO.

COMEFROM kira-kira kebalikan dari GOTO dalam hal itu dapat mengambil status eksekusi dari titik sembarang dalam kode ke pernyataan COMEFROM. Titik di mana kode transfer negara terjadi biasanya diberikan sebagai parameter untuk COMEFROM. Apakah transfer terjadi sebelum atau setelah instruksi pada titik transfer yang ditentukan tergantung pada bahasa yang digunakan. Bergantung pada bahasa yang digunakan, beberapa COMEFROM yang merujuk pada titik keberangkatan yang sama mungkin tidak valid, tidak deterministik, dieksekusi dalam semacam prioritas yang ditentukan, atau bahkan mendorong eksekusi paralel atau sebaliknya seperti yang terlihat dalam Threaded Intercal. Contoh sederhana dari pernyataan "COMEFROM x" adalah label x (yang tidak perlu ditempatkan secara fisik di dekat COMEFROM yang sesuai) yang bertindak sebagai "pintu perangkap". Ketika eksekusi kode mencapai label, kontrol diteruskan ke pernyataan setelah COMEFROM. Efek dari hal ini terutama membuat debugging (dan memahami aliran kontrol program) sangat sulit, karena tidak ada indikasi di dekat label bahwa kontrol secara misterius akan melompat ke titik lain dari program.

Jeff Foster
sumber
16
Cukup jahat - mengubah label menjadi GOTO. Kedengarannya seperti peretas fitur bahasa yang akan meminta ...
RCIX
114
Ok, tapi INTERCAL seharusnya lucu - ini sebenarnya bukan "gotcha" yang mengejutkan. Kompilator INTERCAL sebenarnya dapat menolak untuk mengkompilasi program jika Anda tidak PLEASEcukup sering menggunakan pengubah!
Groo
10
Kedengarannya seperti AOP :)
akuhn
6
Yang paling mengejutkan saya adalah bahwa dalam analisis persyaratan sistem dalam "Dunia Komersial TI", COMEFROM sebenarnya digunakan dalam file teks yang menggambarkan Use Cases. (serius: beberapa analis di sini menunda migrasi seluruh perusahaan ke OpenOffice alih-alih MS's Office karena yang pertama tidak dapat merujuk dengan benar "kedatangan dari" dengan rincian yang diperlukan dalam tautan)
jsbueno
5
Groo: Ini lebih buruk. Gunakan PLEASE terlalu sering dan ia menolak untuk mengkompilasi program Anda karena Anda sedang bersedih (C-INTERCAL membutuhkan antara 33% dan 66% pernyataan untuk memiliki PLEASE modifier).
Vatine
160

Bukan fitur bahasa, tapi cacat implementasi: Beberapa kompiler Fortran awal mengimplementasikan konstanta dengan menggunakan kumpulan konstan. Semua parameter dilewatkan dengan referensi. Jika Anda memanggil suatu fungsi, mis

f(1)

Kompiler akan meneruskan alamat konstanta 1 di kumpulan konstan ke fungsi. Jika Anda menetapkan nilai ke parameter dalam fungsi, Anda akan mengubah nilai (dalam hal ini nilai 1) secara global dalam program. Menyebabkan beberapa kepala menggaruk.

Richard Pennington
sumber
124
Ooh. Maka 2+2 bisa sama 5(untuk nilai yang sangat besar 2tentunya!).
Alok Singhal
12
um, berapa nilai 2 yang akan menghasilkan "2 + 2" == "5"? Saya tidak tahu ada nilai integer 2 yang bisa berlaku untuk itu.
Aaron
36
@earlz: Saya menduga itu akan berakhir sebagai nilai integral, dari pola bit apa pun. Di sisi lain, Anda mungkin dapat mengatur 5 hingga 4 dengan cara itu (sehingga 2+2akan sama 5dengan nilai kecil 5).
David Thornley
18
Maaf, Alok, tapi ini FORTRAN awal yang sedang kita bicarakan. Itu tidak benar bahwa 2 + 2 = 5; itu akan menjadi kesalahan sintaksis. Apa yang akan benar adalah 2 + 2 .EQ. 5.
David Thornley
3
Di Haskell, cuplikan berikut ini menjadi 5: "biarkan 2 + 2 = 5 in 2 + 2" :)
Tirpen
153

Tidak tahu apakah itu dapat dianggap sebagai fitur bahasa, tetapi, di C ++ hampir semua kesalahan kompiler yang terkait dengan templat memberikan WTF ke banyak programmer C ++ di seluruh dunia setiap hari :)

Dmitry
sumber
15
Tidak apa-apa, sebagian besar kode yang terkait dengan templat sudah menciptakan banyak WTF di seluruh dunia.
Joris Timmermans
43
Oh, sekarang. referensi tidak terdefinisi ke `std :: basic_ostream <char, std :: char_traits <char>> & std :: operator << <std :: char_traits <char>> (std :: basic_ostream <char, std :: char_traits <char> > &, char const *) 'Mudah dibaca!
Matt Greer
10
Saya pernah memiliki kesalahan kompiler terkait template yang lima baris, yang terpendek adalah tujuh belas ribu karakter (klasik 'tidak cocok untuk x' kesalahan, dalam program yang sangat templated). Itulah WTF, bukan fitur di tempat pertama, templat sangat bagus.
Andrew McGregor
111
Meskipun tidak ada kesalahan, coba temukan fungsi mana yang paling lama menggunakan profiler Anda. Oh, lihatstd::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
Saya pikir ini cocok di sini: Lihat STLFilt di bdsoft.com/tools/stlfilt.html untuk membuat output dapat dibaca.
foraidt
150

Banyaknya ruang nama C:

typedef int i;

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

Atau dengan karakter:

typedef char c;

void foo()
{
    struct c {c c;} c;
    c: c.c = 'c';
    printf( "%c\n", c.c);
}
Victor Hurdugaci
sumber
Bagaimana ini bisa dikompilasi dengan jelas !?
Earlz
13
+1 Pengidentifikasi tag untuk enum dan struct adalah bagian yang paling membingungkan dari C imho. Hanya sedikit orang yang mengerti mengapa idiom untuk mengetik pointer ke struktur terlihat seperti itu.
Tadeusz A. Kadłubowski
11
Itu mengkompilasi karena setiap orang yang saya punya namespace jelas karena konteks.
Andrew McGregor
149

Saya akan mengatakan seluruh ruang putih Python adalah fitur WTF terbesar saya. Benar, Anda lebih atau kurang terbiasa dengan itu setelah beberapa saat dan editor modern membuatnya mudah untuk ditangani, tetapi bahkan setelah sebagian besar pengembangan python penuh waktu selama setahun terakhir, saya masih yakin itu adalah Ide Buruk. Saya sudah membaca semua alasan di baliknya tetapi jujur, itu menghalangi produktivitas saya. Tidak banyak, tapi masih duri di bawah pelana.

edit: menilai dari komentar, beberapa orang tampaknya berpikir saya tidak suka membuat indentasi kode saya. Itu penilaian yang salah. Saya selalu membuat indentasi kode apa pun bahasanya dan apakah saya dipaksa atau tidak. Apa yang saya tidak suka adalah bahwa itu adalah lekukan yang menentukan apa yang menghalangi suatu baris kode. Saya lebih suka pembatas eksplisit untuk itu. Di antara alasan lain, saya menemukan pembatas eksplisit membuatnya lebih mudah untuk memotong dan menempelkan kode.

Misalnya, jika saya memiliki blok indentasi 4 spasi dan tempel di akhir blok yang diberi indentasi 8 spasi, editor saya (semua editor?) Tidak tahu apakah kode yang ditempelkan milik blok 8-ruang atau bagian luar blok. OTOH, jika saya memiliki pembatas eksplisit, sudah jelas kode mana yang menjadi milik blok dan bagaimana seharusnya (ulang) indentasi - ia melakukannya dengan secara cerdas mencari pembatas blok.

sunting 2: beberapa orang yang memberikan komentar sepertinya berpikir ini adalah fitur yang saya benci atau yang saya pikir menjadikan python bahasa yang buruk. Sekali lagi, tidak benar. Meskipun saya tidak terlalu menyukainya, itu intinya. Pertanyaannya adalah tentang fitur bahasa yang paling aneh , dan saya pikir ini aneh, karena itu menjadi sesuatu yang sangat, sangat sedikit (tetapi> 0) bahasa yang digunakan.

Bryan Oakley
sumber
63
jika itu menghalangi produktivitas Anda maka kode non-python Anda tidak bisa sangat mudah dibaca ...
Tor Valamo
27
Bahasa apa yang Anda gunakan sebelum Python? Bagaimana Anda bisa bekerja dengan orang lain dan tidak menggunakan bahasa itu? Bagaimana orang bisa tahan dengan kode non-indentasi dalam bahasa apa pun ? Apakah Anda bekerja di ruangan yang penuh dengan para genius yang tidak membutuhkan isyarat visual dalam kode sumber?
S.Lott
53
+1 Tidak dapat menyetujui lebih banyak, jika editor saya (Emacs) tidak dapat membuat indentasi kode saya berdasarkan sesuatu yang berbeda (seperti kawat gigi / mulai, akhiri / beri nama) secara otomatis, itu sungguh konyol. Hampir semua refactoring yang Anda lakukan pada fungsi "lebih besar" bisa menjadi pengalaman yang sangat buruk.
Dmitry
83
Inilah yang terjadi - dengan bahasa lain, saya dapat menyorot satu blok kode dan memasukkannya dengan benar oleh editor mana pun. Tetapi karena ruang putih IS dengan definisi indentasi yang tepat, Anda kehilangan kemampuan itu dengan Python. Jadi lebih sulit untuk memindahkan kode atau refactor. Dan untuk orang yang mengklaim OP adalah "orang pertama yang mengklaim itu adalah masalah", saya harus mempertahankan beberapa kode python untuk sementara waktu dan sekarang saya akan menggunakan bahasa apa pun di atas python karena alasan ini.
Kendall Helmstetter Gelner
38
Saya tidak keberatan dengan spasi putih di Python. WTF adalah bahwa itu tidak ditegakkan secara konsisten. Anda dapat mencampur level dan tab indentasi, asalkan konsisten dengan saudara mereka. Jadi level indentasi pertama bisa satu spasi, dan yang kedua bisa dua TAB, dan ini bukan kesalahan sintaksis.
Yaitu
138

Saya berjuang sedikit tentang ini:

1;

Dalam perl, modul perlu mengembalikan sesuatu yang benar .

miku
sumber
29
Beberapa modul dapat mengembalikan nilai berdasarkan operasi runtime. Jika Anda selalu mengembalikan true, Anda masih tidak harus bersikap tidak kreatif tentang hal itu: returnvalues.useperl.at
Anonymous
8
Jika memori Perl saya berfungsi dengan benar, mengembalikan true dari modul menunjukkan bahwa modul berhasil dimuat. Mengembalikan nilai yang salah berarti bahwa ada yang salah dan akan mencegah program berjalan (jika tidak tertangkap).
Barry Brown
Ini adalah pernyataan C yang valid juga, hanya tidak ada yang dikembalikan.
sigjuice
24
Mark Dominus menulis, "Saya sangat jarang menggunakan 'Cogito ergo sum';yang seperti yang diketahui semua orang adalah terbukti dengan sendirinya di semua alam semesta yang memungkinkan. Ini memastikan portabilitas maksimum."
Greg Bacon
PHP <?=1;?>mengembalikan 1. <?=true;?>mengembalikan 1. <?=false;?>mengembalikan null.
Talvi Watia
135

Saya terkejut bahwa tidak ada yang menyebutkan 7 loop konstruksi 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

Karena menempelkan! di depan kondisimu terlalu rumit!

Jeff Atwood
sumber
47
Mereka seharusnya membuatnya " Whiledan Whend", karena ada beberapa orang yang mengucapkan kata "sementara" dengan aproksimasi velar yang tidak bersuara yang tidak bersuara. Dan tentu saja itu berbaris lebih baik, dan kode yang berbaris itu bagus.
dreamlax
43
Kenapa kau bersikap begitu aneh?
Erik Forbes
48
Wow. Saya jadi agak nostalgia ketika memikirkannya. Pertama kali saya menggunakan VB adalah kembali saat berusia 9 tahun. Saya dari Swedia, dan tidak terlalu fasih berbahasa Inggris saat itu. Sekarang, ada kata Swedia yang disebut "vänd" yang pada dasarnya berarti "kembali" dan yang diucapkan sama dengan "wend". Karena itu saya pikir itu masuk akal ... :)
Emil H
61
! tidak bukan dalam VB, itu "Tidak". Atau itu? Ya, tidak bukan !, tapi Tidak.
brianary
7
Ya, "Wend" adalah kata bahasa Inggris, yang berarti pergi atau melanjutkan kursus atau cara ( google.com/search?q=define%3A+wend ). Saya tidak yakin apakah itu membantu atau menyakitkan.
Michael Myers
134

Bagi mereka yang tidak tahu, bcadalah "bahasa kalkulator presisi arbitrer", dan saya menggunakannya cukup sering untuk perhitungan cepat, terutama ketika jumlah yang terlibat besar ( $adalah prompt):

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

bctelah menjadi perintah standar Unix untuk waktu yang lama.

Sekarang untuk "fitur WTF". Ini dari man bc(penekanan milikku):

berhenti : Ketika pernyataan berhenti dibaca, prosesor bc dihentikan, di mana pun pernyataan berhenti ditemukan. Misalnya, "jika (0 == 1) berhenti" akan menyebabkan bc berakhir.

berhenti : Pernyataan berhenti (ekstensi) adalah pernyataan dieksekusi yang menyebabkan prosesor bc berhenti hanya ketika dieksekusi. Misalnya, "jika (0 == 1) berhenti" tidak akan menyebabkan bc untuk berhenti karena berhenti tidak dijalankan.

Alok
sumber
41
Saya menggunakan Haskell untuk barang ini.
Thomas Eding
8
Google kalkulator?
igul222
7
Saya sudah mulai menggunakan Python sendiri, dan google kalkulator bagus jika Anda online. Tetapi saya biasa menggunakannya bcsebelum itu, dan ingin menulis tentang bcdi posting saya karena kutipan hebat dari halaman manual.
Alok Singhal
6
@ Brian, maka Anda akan menyukai: echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc(meskipun Anda mungkin sudah tahu ini).
Alok Singhal
2
Saya menggunakan irb (shell interaktif Ruby). Tapi kembali pada hari itu, saya selalu meraih dc seperti bc, tetapi menggunakan reverse polish. Geektastik!
tragomaskhalos
134

Saya selalu bertanya-tanya mengapa program paling sederhana adalah:

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

Padahal bisa jadi:

print "Hello World!"

Mungkin ini untuk menakuti siswa ilmu komputer di tempat pertama ...

Didier Trosset
sumber
34
Dalam beberapa bahasa, "Hello World!" adalah program yang valid.
David Thornley
31
@SoMoS: dalam sebagian besar bahasa dinamis seperti Python, Ruby, atau Perl, "Hello World!" atau beberapa variasi kecil (mis. menempatkan bukan cetak) adalah program yang valid dan lengkap.
Dave Kirby
36
@Loadmaster: implikasinya adalah bahwa "semua kode termasuk dalam kelas" atau "semua kode termasuk dalam suatu fungsi" adalah kendala yang tidak perlu
Jimmy
19
Hanya karena suatu bahasa memberlakukan penggunaan objek, tidak berarti itu digunakan untuk pemrograman berorientasi objek yang tepat. Sangat mungkin untuk memprogram secara prosedural dalam Java atau C #. Itulah gunanya metode statis.
jdmichal
68
Saya suka orang yang berpikir OOP berarti segala sesuatu harus menjadi objek.
Tor Valamo
132

JavaScript berorientasi objek, bukan? Jadi menjalankan metode pada string dan angka literal harus bekerja. Suka "hello".toUpperCase()dan 3.toString(). Ternyata yang kedua adalah kesalahan sintaks, mengapa? Karena parser mengharapkan angka diikuti oleh titik menjadi titik mengambang literal. Itu bukan WTF, WTF adalah Anda hanya perlu menambahkan titik lain untuk membuatnya bekerja:

3..toString()

Alasannya adalah bahwa literal 3.ditafsirkan sebagai 3.0, dan 3.0.toString()berfungsi dengan baik.

Theo
sumber
8
Bekerja dengan cara ini di Python juga (coba 3..__add__(4)). Kemudian lagi saya pikir (3).__add__(4)adalah cara yang jauh lebih sedikit kerusakan otak untuk melakukannya :)
badp
49
Anda bisa melakukan (3) .toString ()
Joseph Montanez
13
@ Gorilla3D: yeah, tapi itu bukan fitur bahasa yang aneh, bukan?
Theo
25
3.0.toString()membuat mataku gatal.
Ben Blank
18
127.0.0.1.toInt ()
berkus
130

Dalam JavaScript:

2 == [2]

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

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

Untungnya orang-orang baik di stackoverflow.com menjelaskan semuanya kepada saya: Mengapa 2 == [2] dalam JavaScript?

Xavi
sumber
6
Itu sebabnya Anda harus menggunakannya ===.
Gumbo
10
Ini berguna, jika Anda memiliki fungsi yang mengembalikan nomor dan Anda ingin mengembalikan beberapa metadata tambahan, Anda dapat mengembalikan [angka] dengan beberapa bidang tambahan ditambahkan. Kode sederhana tidak akan pernah tahu itu bukan bilangan real, dan kode lain bisa mendapatkan metadata yang diperlukan.
Andrey Shchekin
36
@Andrey kecuali bahwa jika saya harus mempertahankan kode yang melakukan apa yang Anda sarankan, saya akan segera berharap kematian penulisnya.
Breton
@ Andrew, itu ide bagus! Anda juga dapat menggunakan Number(n)untuk melakukan hal serupa. Sayangnya di kedua solusi kami ===break = (.
Xavi
5
+1: Saya menganggap diri saya seorang programmer js yang berpengetahuan luas, dan saya tidak pernah tahu tentang ini: D
Thomas Eding
126

Fitur terbesar saya yang paling dibenci adalah sintaksis file konfigurasi yang menyertakan logika kondisional. Hal semacam ini marak di dunia Jawa (Semut, Maven, dll. Anda tahu siapa Anda!).

Anda baru saja mengakhiri pemrograman dalam bahasa ac ** p, dengan debugging terbatas dan dukungan editor terbatas.

Jika Anda membutuhkan logika dalam konfigurasi Anda, pendekatan "Pythonic" dalam mengkode konfigurasi dalam bahasa nyata jauh lebih baik.

James Anderson
sumber
24
Tcl menemukan kembali bahwa jauh sebelum Python lahir dan Lisp menciptakannya sebelum itu. Jadi jangan sebut itu Pythonic, sebut saja Emacs-ish.
Slebetman
46
Sebut saja Benar.
mletterle
30
AMIN. Jika konfigurasi atau bahasa build Anda selesai, Anda salah melakukannya. Saya melihat Anda CMake / autotools.
Joseph Garvin
16
Inilah tepatnya yang dirancang untuk Lua, awalnya
Cogwheel
1
Nah, jika kode Anda menggunakan Python, maka memiliki file konfigurasi Anda menjadi file Python adalah ide yang bagus, karena Anda kemudian hanya mengimpor file dan membaca atribut dari modul. Dan Anda mendapatkan kekuatan Turing 100% Lengkap Python di file konfigurasi Anda.
penanggung jawab
113

powerbasic (www.powerbasic.com) termasuk arahan kompiler:

# BLOAT {bloatsize}

ini meningkatkan ukuran dari executable <bloatsize>bytes yang dikompilasi . ini dimasukkan ke dalam kompiler kalau-kalau orang membuat executable tidak suka ukuran kecil executable yang dihasilkan. itu membuat EXE tampak lebih besar untuk bersaing dengan bahasa pemrograman yang membengkak :)

Don Dickinson
sumber
9
Haha yuk. Saya pernah mendengar tentang pengembang yang sengaja memperlambat beberapa operasi (misalnya pencarian) karena ini membantu orang percaya bahwa itu benar-benar melakukan sesuatu. Saya kira hal serupa.
David
42
Ini mengingatkan saya pada sesuatu yang saya baca baru-baru ini. Mereka menguji FPS dan memutuskan untuk menambah jumlah hit point yang dimiliki orang jahat. Kemudian mereka bertanya kepada penguji bagaimana mereka AI, dan mereka bersumpah itu jauh lebih pintar. Tetapi AI tidak berubah, hanya poin hit. Orang-orang memiliki narasi tertentu tentang dunia di kepala mereka, dan jika Anda memahami dan mencocokkan harapan mereka, mereka hanya akan menganggapnya memvalidasi narasi mereka.
Nate CK
5
Saya biasa menambahkan banyak perlambatan ekstra ke program saya untuk membuat mereka terlihat seperti mereka melakukan sesuatu yang rumit. Kembali ke sekolah dasar, itu.
Matti Virkkunen
3
Kembali di sekolah kami memiliki 80.286 mesin dan saya benar-benar harus menulis beberapa rutinitas layar output dalam perakitan untuk mendapatkan kecepatan yang wajar (yaitu tidak merangkak).
Berkus
7
@Nate CK, jika AI hidup cukup lama untuk memamerkan AI-nya, itu mungkin sebenarnya lebih pintar, sedangkan sebelum itu mungkin mati terlalu cepat untuk membuktikannya.
zzzzBov