作者godfat (godfat 真常)
看板PLT
標題Re: 何謂「好的」程式語言
時間Thu Feb 22 16:50:37 2007
※ 引述《PsMonkey (痞子軍團團長)》之銘言:
: 面對 C 家族的狂熱分子
: Java 典型被批判的就是「沒有指標」
: 或著應該說「沒有辦法直接用指標」
^^ 者
: 甚至有人用「全梭了」的肯定語氣跟我說
: 「沒有指標很難寫程式」
老實說,我以前也會這樣說 :p
算是一個懵懂時期的重大錯誤之一吧 [遠目]
不過其實這件事可能還在不早之前…這就不多提了
主要的問題點在於,那時我完全不懂 Java,
不懂 Java 說「沒有指標」這件事到底是指什麼。
以下假設讀者懂 Java reference 也懂 C/C++ pointer,
不懂的話請多看書或提出討論 XD
這篇文章中的一個標題(不用看,跟本文無關,但可參考):
http://www.cs.caltech.edu/~mvanier/hacking/rants/
scalable_computer_programming_languages.html
縮
http://rubyurl.com/uQC
「Direct access to memory and pointer arithmetic: very bad」
真正的燙手山芋其實是這句話裡的東西,而非 pointer 本身。
而 Java 到底有沒有 pointer? 就我的觀點,有,只是不能以之運算罷了。
在 C/C++ 中,東西是可以建立在 stack 上的,而當你把他 pass around 時,
則是 pass by value, 是把整個東西 bitwise copy 丟過去。
而我呢,在還沒接觸 Java 前,以為所有的東西都必須這樣 bitwise copy...
這種程式語言能用才怪,這樣寫 sub-routine / sub-program / function
豈不是大吃資源?怎麼可能能用?
再者,Java 的 reference, 跟 C++ 的 reference 根本毫無關係…
C++ 的 reference 是 alias, 即決定了就不能改變了,也不能是 NULL 的
reference, 即每個 reference 一定要 refer 某樣東西,而且永遠是那東西。
ok, 在這種狀況下告訴我 Java 沒有 pointer, 只有 reference,
怎麼能接受呢? Orz
但事實上,Java 的 reference 在 well-written 的 C++ 裡,
其意思跟 C++ 的 pointer(包括 smart pointer)是差不多的。
Java 的 reference 不能運算,即不能寫
Object o;
o += 1;
不能比較
Object o1, o2;
boolean b = o1 < o2;
不能取得變數本身(取址以便做 alias)
Object o;
Variable v = &o;
除此之外跟 pointer 應該是沒什麼差別了(暫時想不到)
而沒有這些會不會有什麼問題?我敢說,絕對不。
alias 當然很方便,但其實也造成很多問題。(這邊不講了,會扯很遠)
指標運算更是 error-prone, 某種程度上也會跟硬體相依。
上面那篇文章說:「very bad」
基本上我是同意的。只是我是覺得反正就不要用,工具放著又不會來咬人,
也許哪天還是要用到啊,倒也不必視為毒蛇猛獸就是了。
另外 Java 也沒有 stack 上的 object, 一定要用 new 來建立
所以有沒有 pass by address/reference, 也不是那麼重要了…
這種情況下,到底該不該說沒有 pointer? 我保留,但尊重 Sun 的術語,
所以談到 Java 時仍然使用 reference 一詞。再講到 C/C++ 的話,
我會稱 Java 的 reference 是閹割過的 pointer, 否則容易跟 C++ 的
reference 搞混。
我想會講「沒有指標很難寫程式」這句話,有三種可能:
1. 跟我一樣誤會了 Java 術語
2. 他要做硬體操作
3. 他要做非常重要的最佳化
結論是,不要再相信沒有根據的說法了 ><
受夠一些廣告用詞了……
: 夾在兩造雙方之間,其實就平民小卒來說,還挺困擾的
廣告太多,誤解太深,解決之道,親自一探
: 同樣的事情也發生在 gc、效率等等問題上
Modern C++ Design 作者 Andrei Alexandrescu,
(
http://en.wikipedia.org/wiki/Andrei_Alexandrescu 這人現在好有名啊…)
在 comp.lang.c++.moderated 上說,GC 可能是 programming 界被誤解最深的東西
簡單地說,他認為 GC 的好處太多了,而事實上,有些時候 GC 反而能增進效率。
因為有的時候,release 時機是很難處理的,這時候 GC 處理效率會比人高。
另外還有一個很好的範例,顯示 GC 如何處理一個棘手的 return 問題:
…抱歉,我忘了是什麼情況 囧rz
希望有人可以指出 Orz
總之大意就是,你必須在 function return 完之後釋放資源。
可是這在一般流行的程式語言中,是不可能用簡單方法辦到的,
因為 return 之後 function 就跳離了,又不能這樣寫:
return result;
release(temp); // 當然此例可以拉到 return 上面,但我記得有種狀況是不行的
難道要這樣嗎?
try{} finally{ release(temp); }
return result;
不過這樣似乎變成一定要 release 了,不能用成緊接在 return 之後
比較蠢的方法可能可以這樣做:
register_call_after_1_second( bind(&release, temp) );
return result;
註冊一個一秒後會呼叫的 function, return 應該不用執行一秒…
另外還有一個很有說服力的例子,被我提了好多次,
就是某個字串處理的問題,由 D 和 C++ 的程式分別寫成
我沒記錯的話,就是這個頁面裡的程式
http://www.digitalmars.com/d/cppstrings.html
D 能夠跑比較快的優勢是擁有 sub-array view,
而實作這樣東西是需要 GC 的輔助,類似上面那樣的狀況。
其實這些討論我也是從 comp.lang.c++.moderated 看來的
有人說他可以把 C++ 寫到跟 D 差不多快,可是得用很多骯髒的手法…
寫得漂亮一點的話,執行效能就敗給 D 不少了
C/C++ 也有個名 GC 實作,叫 Boehm GC
http://www.hpl.hp.com/personal/Hans_Boehm/gc/
這東西的使用者其實還蠻多的,很多大型計劃也有使用
C++0x 的 GC 設計也跟此 GC 有很大的關聯
GC 已經差不多變成現代高階語言必備的東西了,C++ 在這裡走得稍嫌慢了點
: gc 是很消耗 resource 的行為
對於小程式來說,GC 是額外吃了不少資源,用處不大
畢竟小程式自己管理記憶體也不會是什麼難處
但對於大程式來說,GC 所消耗的資源會變得不明顯
當然,記憶體受限的 embedded 環境可能也不便用 GC
不過以 PC 來說,GC 所帶來的壞處其實很不明顯了
: 那麼,是要賭自己控制 resouce 會比較好
: 還是期望語言本身提供 gc 的演算法可以達到「可接受」的範圍?
: 因為我是笨蛋,而且我相信開發 JVM 的人比我聰明百倍...
這個其實就比較難講了,客製的當然會更容易比通用的效率好
不過隨著時間不斷演進,通用的也越來越不會有什麼問題了…
: 但是,又有人跟我講
: Java 沒辦法處理很大量資料的狀況
: 所以他雖然是從 Java 起家的,不過後來還是乖乖寫 C
: (他好像是作即時影像處理的,然後隨便就是幾百MB 的資料在記憶體當中)
: hmmm... 還沒寫過那種恐怖的東西... 很難想像
: 但是 Java 真的作不到嗎? 好像也很難想像...
: 也許作起來要花很多功夫?
這我不知道 Orz
不過很多極端吃系統資源的程式,就我所知在 JVM 上都不好發揮
感覺會是綁手綁腳
: 但是... 能不能把這個狀況當作是極端狀況來對待?
: 我的意思是... 畢竟一般人寫一般程式
: 用 Java 好像很快樂也不容易出大紕漏?
: 我們畢竟會常常需要用到動態決定大小的陣列
: 而很少要處理很大量很大量的資料?
我可不可以說所以 Java 現在人口排行第一? :p
http://www.tiobe.com/tpci.htm
其實 C++ 會排第三也蠻神奇的,我個人覺得
C++ 這種瘋狂複雜的東西,我不信能有那麼多人搞懂…
最上面貼的那篇文章(Scalable computer programming languages)也說:
Even though C++ is monstrously complex,
the ability to write code that moves smoothly
from a bit-level of abstraction to a fairly high level
of abstraction is extremely valuable for many projects,
especially ones where efficiency is paramount.
I intend to do more C++ programming and also to use
the Boehm-Demers conservative GC to see how effective it is in
combination with C++'s other features.
隨意翻譯:
「儘管 C++ 是妖獸(XD)般地複雜,能從位元等級的抽象層平順地
移動到高階等級的抽象層,對於很多專案來說都是極端有價值的,
尤其是那些效率極為重要的專案。
我有意進行更多的 C++ 程式設計,也開始使用傳統的 Boehm GC,
以之看看該 GC 如何有效地和 C++ 其他功能合併在一起。」
*
順便再提一下 Beyond Java 這本書。
其實我之所以對此書有相當的不以為然,
有一個很大的原因就是他很明顯不懂 C++,
然後卻把 C++ 罵個半死。
(用這種態度去評論,其他的評論可信度?存疑)
上文的作者一開始也是不懂 C++,
不過語句保留,且最後他也同意了 C++ 是如此 powerful,
他願意做更多的嘗試。(推測是被很多人 email 去罵了… XD)
: 寫到這裡,似乎就能預料有神人級的人會跳出來說
: 「語言只不過是工具,視狀況而決定工具
: 所以討論工具好壞是沒有意義的」
我覺得這樣講當然不對,因為這樣講的話根本啥屁都不用討論了。
我們只要顧著使用工具,或是顧著亂做一堆工具出來,好壞不管,
每個工具自有他的用處?秉持著這種精神,又怎麼能夠進步?
每個遊戲都有他的愛好者,所以我們遊戲可以亂做?當然不對。
所以一個遊戲好壞不重要,因為自有愛好者?這也當然不對…。
: 這樣講好像很對,但是又好像很不對
: 畢竟,像我這種笨蛋... 連 Java 都寫的不是很好了
: 要視狀況在工具之間跳來跳去,似乎有摔死的可能 Orz
: (當然,現實狀況是... 環境逼著你跳,你不得不跳)
這個嘛…應該還是要在自己會的工具裡面跳。
只有一個工具當然就不用跳了,那叫做沒得選擇 XD
所以學會越多工具,就要越能有分辨工具好壞的能力…
這算是一種期許吧?
: 又反過來說,面對另外一群人
: 他們會 argue Java 不夠快 or 不夠簡單
: 像 Perl 的使用者會覺得 Java 宣告起來很麻煩、字串處理很麻煩
: Ruby 的使用者會說 Java 寫起來不夠快
: (恩... 不過看到的好像大部分是針對 Web 開發的部份?)
我好像沒聽過有什麼用 Perl 寫成的超大型程式。
我想這一群人,目標本來就不是那種超級大型的程式。
畢竟 Perl 又常常被稱為 glue langauge, 是吧 :p
根據這裡:
http://en.wikipedia.org/wiki/Glue_language
Ruby 也算呢…。
不同的語言當然有不同的著眼點,個人認為有些語言的比較,
其實也已經有點變成是沒搞清楚什麼語言該做什麼事了…。
不過有些時候確實是因為不會而沒得選擇,像是早先我常用 C++
寫字串處理程式,理由很簡單,因為我只會這個…。
要我花十個小時學好最適合該問題的語言,然後再花十秒鐘解決問題,
我寧可花十分鐘用我現在會的東西趕快解決問題…。
: 另外一個... 囧點...
: 是好像很少人會把 C 家族跟 Perl, Ruby 來作對比
: (至少 PTT 的討論版很少看到)
: 但是 Java 會拿來跟 C 家族來比較,也會被拿來跟 Ruby 來比較
這個其實一直是我覺得很妙的地方,哈哈 XD
Perl 和 Ruby 很明顯就是 scripting language, 他的目標很明確。
C/C++ 也很明確,就是 system language, 絕對是拿來處理大問題的。
可是 Java 呢…?我個人覺得 Java 本身的處境其實很尷尬,
因為他介於 system language 和 scripting language 之間。
他比 C++ 更動態,但是遠遠沒有 Perl 和 Ruby 來得動態。
於是這造成了一種,我覺得很詭異的局面。
最簡單的例子就是容器了,在 Java 1.5 之前,容器一律用 Object 存:
Vector v = new Vector();
v.add("XD");
String s = (String)v.get(0);
看到這種東西,真的讓我很想翻桌。
啊既然我都要用靜態型別了,為什麼又要我在 runtime 轉型?
不過另外一個說法是,反正容器就是要泛用,所以可以存任何東西。
ok, 我沒意見,C++ 的 boost 也有 any 這種泛用指標。(which is type safe)
Java 1.5 加入 generic 後,整個狀況其實變得更詭異了…
Vector<String> v = new Vector<String>();
// ok, verbose 這件事這裡不討論,好的解決辦法叫 type inference
v.add("XD");
String s = v.get(0);
用程式碼看起來,問題是解決了沒錯。可是 runtime 上他還是存 Object...
所以基本上只是提供了更多型別安全,還有讓你少打點字。(算是改進…吧?)
但是就整個設計面來看,實在是有點矛盾……要靜不靜,要動不動…
我覺得,Java 在很多地方都卡在這種矛盾之中,搖擺不定。
一方面想搶 C++ programmer(他成功了!),
另一方面又想搶 scripting language 的飯碗……
問題是,根本不可能有這麼萬能的語言和系統,兩邊可以通吃。
於是 C++ 視 Java 為敵人,Ruby 也視 Java 為敵人……
然後 Sun 為了打敗 C++, 加入 XX 特性(這邊再用 OO 就要誤解了 XD)
然後 Sun 為了打敗 Ruby, 加入 YY 特性
原本好像很單純的 Java, 現在對我來說,他真的長得有點畸形……。
不可否認他用起來是不難,但是,其實就像
Scalable computer programming languages 這篇文章所說,
I think Java is a fine language for many types of applications,
but it doesn't have the qualities of coolness that make me
fall in love with a language, and the abstraction level is still
less than many other languages, including C++.
(不翻了…寫太久了)
Java 用在寫應用程式上是不錯,但是他實在缺少一個讓人愛上他的…特質?
畸形也許很好用,但他不美。
(很多人說 Lisp 很美,大概是因為幾乎沒有語法吧 :)
我也很崇尚這種 simplicity.)
: 這個問題的切入點,以我淺薄的知識也想得出一些
: 不過一開始還是先隨意吧... 這樣子標靶比較大一點... [茶]
: 所以上頭就寫的很鬆散... XD
: 反正收斂焦點 & 收是版主要煩惱的... [逃]
Orz
我扯太多了,害我現在很累,想睡覺了
收斂焦點無妨吧?但沒有焦點很難處理倒是真的 Orz
幸好其實也不是要出書,有點亂我想是無妨
--
Hear me exalted spirits. Hear me, be you gods or devils, ye who hold
dominion here:
I am a wizard without a home. I am a wonderer seeking refuge.
Sacrifice
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.28.18
1F:推 coolcomm:推 2013/ 07/25 12:57