作者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