Apa, menurut Anda, fitur bahasa yang paling mengejutkan, aneh, aneh atau benar-benar "WTF" yang Anda temui?
Harap hanya satu fitur per jawaban.
Apa, menurut Anda, fitur bahasa yang paling mengejutkan, aneh, aneh atau benar-benar "WTF" yang Anda temui?
Harap hanya satu fitur per jawaban.
Jawaban:
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.
Dalam JavaScript:
'5' + 3 gives '53'
Sedangkan
'5' - 3 gives 2
+
untuk rangkaian senar itu mengerikan
Dalam JavaScript, konstruk berikut
return
{
id : 1234,
title : 'Tony the Pony'
};
kembali adalah kesalahan sintaksis karena penyisipan titik koma implisit licik pada baris baru setelah undefined
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;
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
==
di mata perancang bahasa?
==
memiliki arti ===
, dan kemudian ada operator lain, sesuatu seperti ~=
itu memungkinkan pemaksaan tipe.
Trigraph dalam C dan C ++.
int main() {
printf("LOL??!");
}
Ini akan dicetak LOL|
, karena trigraph ??!
dikonversi menjadi |
.
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
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 127
kecuali 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;
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;
}
Control cannot leave the body of a finally clause
return
di finally
klausa.
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
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) );
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 errno
sebagai 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 apaAda lebih banyak dari mana mereka berasal. Baca daftar selengkapnya di sini .
$[
variabel kejahatan sebagian besar dari mereka semua.
perldoc perlvar
setiap 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)
use English;
adalah itu mempengaruhi kinerja RegExp. Saya tidak mengada-ada. perldoc.perl.org/English.html#PERFORMANCE
/$foo[bar]/
, apakah [bar]
bagian kelas karakter atau subskrip ke array @foo
? Grep perldata untuk jawaban yang menakutkan.
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.
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
, ELSE
Adalah nama-nama variabel)
atau
IF IF THEN THEN ELSE ELSE
( IF
adalah variabel, THEN
dan ELSE
merupakan subrutin)
'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 .
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);
}
}
while
di bagian akhir adalah (bersyarat) JMP
kembali ke do
, yang menjelaskan mengapa Anda dapat melewatkan do
dan masih berakhir di loop.
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]);
}
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]; } }); }
?
Dengan Python:
>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
Bukan WTF, tetapi fitur yang bermanfaat.
(10 > 5 > 1) != ((10 > 5) > 1)
dalam Python.
(funct_a(5)+5 > b > funct_a(5))
hanya memanggil funct_a(5)
sekali. Ini adalah fitur HEBAT!
funct_a
akan dipanggil dua kali dalam contoh itu. Di b > funct_a(5) > c
dalamnya hanya akan dipanggil sekali, sebagai lawan b > funct_a(5) and funct_a(5) > c
.
Di Jawa:
int[] numbers() {
return null;
}
Dapat ditulis sebagai:
int numbers() [] {
return null;
}
const T*
dan T const*
setara, itu T* const
yang mengarahkan pointer. Juga, saya benci font sans.
numbers()[2]
adalah pernyataan hukum.
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.
PLEASE
cukup sering menggunakan pengubah!
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.
2+2
bisa sama 5
(untuk nilai yang sangat besar 2
tentunya!).
2+2
akan sama 5
dengan nilai kecil 5
).
2 + 2 = 5
; itu akan menjadi kesalahan sintaksis. Apa yang akan benar adalah 2 + 2 .EQ. 5
.
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 :)
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> >)
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);
}
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.
Saya berjuang sedikit tentang ini:
1;
Dalam perl, modul perlu mengembalikan sesuatu yang benar .
'Cogito ergo sum';
yang seperti yang diketahui semua orang adalah terbukti dengan sendirinya di semua alam semesta yang memungkinkan. Ini memastikan portabilitas maksimum."
<?=1;?>
mengembalikan 1. <?=true;?>
mengembalikan 1. <?=false;?>
mengembalikan null.
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!
While
dan 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.
Bagi mereka yang tidak tahu, bc
adalah "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
bc
telah 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.
bc
sebelum itu, dan ingin menulis tentang bc
di posting saya karena kutipan hebat dari halaman manual.
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
(meskipun Anda mungkin sudah tahu ini).
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 ...
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.
3..__add__(4)
). Kemudian lagi saya pikir (3).__add__(4)
adalah cara yang jauh lebih sedikit kerusakan otak untuk melakukannya :)
3.0.toString()
membuat mataku gatal.
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?
===
.
Number(n)
untuk melakukan hal serupa. Sayangnya di kedua solusi kami ===
break = (.
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.
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 :)