英文原文:stackoverflow,編譯:外刊IT評論
目前為止,據我個人觀察,從語法角度上講,最被人詬病的一種語言應該是LISP語言了。開啟這種語言的程式碼,一眼望去,滿目全是括弧,一層套一層。 這種語言特徵最大的問題是,它不符合人們通常的思維習慣。LISP語言的這個特點是個整體的語言現象,而任何一種語言其實也都有一些個別的很奇特的東西, 其中有些會奇怪的讓你摸不著頭腦。有一個好事者在一個帖子上徵集各種語言裡不合常理的地方,結果收集到了320多條,問題最大最多的語言算是Javascript了,另外還有C,Java,Python,PHP等等。下面列出的是其中最有趣的幾條。
1、在C語言裡,陣列可以這樣索引取值:
1 |
a[10] |
這種寫法相當常見。
然而,還有一種很少見的寫法(絕對可用!)是這樣的:
1 |
10[a] |
這兩種寫法的效果是一樣的。
2、在JavaScript裡:
1 |
'5' + 3 結果是 '53' |
而
1 |
'5' - 3 結果是 2 |
3、在JavaScript裡,下面的語法結構
1 2 3 4 5 |
return { id : 1234, title : 'Tony the Pony' }; |
會提示語法錯誤:”缺少分號”。而下面的寫法卻能按你預想的結果執行:
1 2 3 4 |
return { id : 1234, title : 'Tony the Pony' }; |
更讓人鬱悶的是下面的寫法竟然可以(至少在谷歌瀏覽器裡是這樣的):
1 2 3 4 5 |
return /* */{ id : 1234, title : 'Tony the Pony' }; |
下面的例子也是同樣的問題引起的,但不會報錯,而你卻得不到想要的結果:
1 2 |
return 2 + 2; |
4、JavaScript的等式對照表:
1 2 3 4 5 6 7 8 9 |
'' == '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 |
5、Java裡有趣的自動打包(auto boxing)和IntegerCache:
1 2 3 4 5 6 7 8 9 10 |
Integer foo = 1000; Integer bar = 1000; foo = bar; // true foo == bar; // false //然而,如果 foo 和 bar 的值介於 127 和 -128 之間, //情況會發生變化: Integer foo = 42; Integer bar = 42; foo = bar; // true foo == bar; // true |
解釋
在Java原始碼裡你很快能翻出下面的內容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/** * 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 的值,如果你不設定它,預設是 127。
自動打包(auto boxing)過程中發生的事情是:除非顯式的建立:比如 foo = new Integer(42) ,否則 foo 和 bar 都是從快取中取出的整數,當比較值時,它們會返回 true。正確的比較Integer的方式是使用 .equals 。
6、在Java裡:
1 2 3 4 5 |
try { return true; } finally { return false; } |
在Python和JavaScript也可以這樣寫。這樣寫的結果是什麼?當作一個保留的問題考考大家吧。
7、C++的模板可以做很多奇怪的事情,最好的例證是 “多維模擬排版”,你可以用模板來計算“畫出的”形狀。下面是一段計算一個3×3矩形的有效的C++程式碼:
1 2 3 4 5 6 7 8 |
#include"analogliterals.hpp" using namespace analog_literals::symbols; unsigned int c = ( o-----o | ! ! ! ! ! o-----o ).area; |
這還有一個3D立方體的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
assert( ( o-------------o |L \ | L \ | L \ | o-------------o | ! ! ! ! ! o | ! L | ! L | ! L| ! o-------------o ).volume == ( o-------------o | ! ! ! ! ! o-------------o ).area * int(I-------------I) ); |
8、PHP處理數字字元
1 |
"01a4" != "001a4" |
如果兩個字串來的字元數不相等,它們不可能相等。前面的零非常重要,因為他們是字元而不是數字。
1 |
"01e4" == "001e4" |
PHP不太喜歡字元,它會尋找任何的藉口來把你提供的值當作數字。把這些十六進位制的字串稍微做些改動,PHP馬上認為它們不再是字元,而是數字。 它們是按科學計數法寫的數字(PHP並不在意你是否用了引號),它們是相等的,因為對於數字來說,前面的零是可以忽略的。更強化這個事實的例子是,你會發 現PHP認為 “01e4″ == “10000″ 是正確的,因為作為數字,它們的值是相當的。這是一個被特別提醒的語言特徵,原因就是它不太合理。
9、在一些沒有保留字、關鍵字的語言裡,例如PL/I, 你可以寫出這樣有趣而且合法的程式碼語句:
1 |
IF IF THEN THEN = ELSE ELSE ELSE = THEN |
(IF, THEN, ELSE 都是變數名),或
1 |
IF IF THEN THEN ELSE ELSE |
(IF 是變數,THEN 和 ELSE 都是函式)
10、JavaScript裡八進位制的轉換:
1 2 3 4 5 |
parseInt('06') // 6 parseInt('07') // 7 parseInt('08') // 0 parseInt('09') // 0 parseInt('10') // 10 |
11、在C語言裡,你可以把 do/while 語句和 switch 交織在一起,下面就是一個使用這種方法的記憶體拷貝的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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); } } |
12、在Python中:
1 2 |
>>> x=5 >>> 1>> 1 |
13、在Java中:
1 2 3 |
int[] numbers() { return null; } |
可以被寫成:
1 2 3 |
int numbers() [] { return null; } |
如果你覺得還沒看夠,請到這裡,還有更多。