C++的抽象惩罚中,有多少是因为强调性能引发的

85 views
Skip to first unread message

莫华枫

unread,
Nov 27, 2007, 7:52:29 PM11/27/07
to TopLanguage
昨晚上想到这样一个问题:
C++的抽象惩罚中,有多少是因为强调性能引发的?有没有不是由于性能造成的?如果有的话是那些?原因是什么?
更进一步,c++的各种缺陷中,有多少是因为强调性能造成的?...

--
反者道之动,弱者道之用
m...@seaskysh.com
longsh...@gmail.com
http://blog.csdn.net/longshanks/

pongba

unread,
Nov 27, 2007, 11:54:32 PM11/27/07
to pon...@googlegroups.com
这个问题我曾经想过,不幸的是,C++中的所有非平凡的语言设计折衷全都是为了性能。
最典型的当然是template的设计。最不典型的估计是求值顺序和序列点问题。
--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba

莫华枫

unread,
Nov 28, 2007, 12:14:42 AM11/28/07
to pon...@googlegroups.com
求值顺序和序列点问题这我明白,但是template为什么是为了性能折中?

up duan

unread,
Nov 28, 2007, 12:20:43 AM11/28/07
to pon...@googlegroups.com
templete是语言设计折衷吗?我觉得C++所有的设计都根源于value语义。当然,你也可以说value语义也是强调性能导致的,但是我倒是觉得性能并不是最本源的考虑。值语义和兼容C才是最主要的设计限制。

On Nov 28, 2007 12:54 PM, pongba <pon...@gmail.com> wrote:

pongba

unread,
Nov 28, 2007, 12:25:26 AM11/28/07
to pon...@googlegroups.com
C++实现GP的机制是template,template是在用(代码)空间换(运行)时间。ruby的GP机制duck-typing则是真正直观的GP。
template的问题在于它不是运行时非绑定的,即:

template<typename T>
void f(T t ) { t.mem_f(); }

这里的mem_f在编译期就已经绑定了,因为编译器必须知道t的类型T。

如果不依赖于t的类型,只依赖于动态绑定的话,就像ruby的:

void f(t) { t.mem_f(); }

template的静态特性使得比如说我们无法建立一个"存储了满足某一特定concept的所有对象的容器":

vector<Plugable> v;

其中Plugable是一个concept。这是不可能的。
C++中传统的解决办法是把Plugable做成一个接口,然后使用适配器设计模式(这是为了弥补接口的侵入性缺陷)。

在Ruby的duck-typing里面,要存放任一满足特定concept的对象易如反掌,直接存就可以了。

莫华枫

unread,
Nov 28, 2007, 12:32:56 AM11/28/07
to pon...@googlegroups.com
但这只是template问题的一半啊,静态非绑定同时也为了获得类型安全性。性能不是全部原因啊?

pongba

unread,
Nov 28, 2007, 12:36:01 AM11/28/07
to pon...@googlegroups.com
1. 类型安全性是建立在强类型的基础上的。而强类型的重点目的之一便是效率(生成高效的代码)。
2. template未必需要完整的信息来获得类型安全性,只需要concept即可。有了concept把关,在template的实现层面便可以完全type-check。而在调用层面,concept则可以作为一道运行期(乃至编译期——如果调用参数的类型信息较全(而不是一个光秃秃的object)的话)的contract来把关,也没有太大问题。

pongba

unread,
Nov 28, 2007, 12:36:39 AM11/28/07
to pon...@googlegroups.com
哎呀,一不小心又把静态类型写成强类型了。
纠正,是静态类型,不是"强类型"。

莫华枫

unread,
Nov 28, 2007, 12:54:28 AM11/28/07
to pon...@googlegroups.com
但是concept化的runtime unbound并未达到runtime unbound同等的特性。
通过动多态,向v插入类型归一化(符合plugable的抽象接口)的对象,可以保证永远是可靠的。但是,向v插入一个"被要求"符合plugable concept的对象,可能会在运行时引发concept失配的异常。在这个程度上两者不等价,也就无法认为concept化的runtime unbound可以作为一个超集覆盖动多态。

pongba

unread,
Nov 28, 2007, 12:57:14 AM11/28/07
to pon...@googlegroups.com
实际上,接口整个儿就是向效率妥协的产物。为了能够迅速地多态调用对象上的方法,接口被做成侵入性的,这样当目标类在编译的时候便能够遵循接口制定的二进制契约(虚函数表),而调用方也将依赖接口制定的二进制契约。如果接口被做成非侵入性的,那么编译器编译目标类的时候便不能知道该建立什么样的二进制布局让调用方来遵循,而只能靠名字查找来动态绑定方法了。

接口以后肯定会成为非侵入性的,实际上接口的侵入性很大程度上影响了语义表达,进而影响了复用性。(为什么要有适配器模式?)

pongba

unread,
Nov 28, 2007, 1:02:06 AM11/28/07
to pon...@googlegroups.com


On Nov 28, 2007 1:54 PM, 莫华枫 <longsh...@gmail.com> wrote:
但是concept化的runtime unbound并未达到runtime unbound同等的特性。
通过动多态,向v插入类型归一化(符合plugable的抽象接口)的对象,可以保证永远是可靠的。但是,向v插入一个"被要求"符合plugable concept的对象,可能会在运行时引发concept失配的异常。在这个程度上两者不等价,也就无法认为concept化的runtime unbound可以作为一个超集覆盖动多态。

把错误推到运行期也许是必要的代价。某种程度上为了实现运行期多态,所有语言都在一些地方把错误推到运行期。(比如向下转型和平行转型)。
此外,如果对象的类型信息是全的,那么这个错误可以在编译期就给出。如果对象的类型信息只有object,那才只能依靠运行期呢。
也就说,如果插入对象时有对象的类型信息,那总是可以早期检查的。如果没有类型信息,那么不管是C++还是ruby中,都得依赖运行期检查。

莫华枫

unread,
Nov 28, 2007, 1:16:37 AM11/28/07
to pon...@googlegroups.com
ok,我明白了。
就是说,我们对于编译期能够确定的,我们应当使用static,而运行期决断的采用runtime,但如论如何都必须是unbound。而应当抛弃bound这种折中的做法。
我觉得这里起决定作用的也并非是简单的性能问题。我认为真正能够打破这层坚冰的,还应当是编程技术的提升。这里的关键是runtime unbound同runtime bound付出的性能损失相比较是否进入人们能够接受的程度。如果哪位牛人使unbound可以达到bound非常接近的性能,甚至同等或超越,那么也不会存在这个问题了。
传统上,为了runtime匹配类型,只能遍历reflection信息,获得type check。但是,在引入concept之后,二进制化的concept信息便会有能力消除这个遍历,直接按照concept信息绑定。问题是,是否能够做到二进制concept。

pongba

unread,
Nov 28, 2007, 1:22:12 AM11/28/07
to pon...@googlegroups.com
On Nov 28, 2007 2:16 PM, 莫华枫 <longsh...@gmail.com> wrote:
ok,我明白了。
就是说,我们对于编译期能够确定的,我们应当使用static,而运行期决断的采用runtime,但如论如何都必须是unbound。而应当抛弃bound这种折中的做法。
我觉得这里起决定作用的也并非是简单的性能问题。我认为真正能够打破这层坚冰的,还应当是编程技术的提升。这里的关键是runtime unbound同runtime bound付出的性能损失相比较是否进入人们能够接受的程度。如果哪位牛人使unbound可以达到bound非常接近的性能,甚至同等或超越,那么也不会存在这个问题了。
 
bound和unbound,两者的调用代价都是O(1)。bound是通过一个间接转发。而unbound则是通过一次hash。
它们两个的调用代价,只是常数倍的关系。我推测,当像并发这样强有力的性能工具出现时,这个常系数的significance就会愈发下降了。

莫华枫

unread,
Nov 28, 2007, 1:23:53 AM11/28/07
to pon...@googlegroups.com
在问题的另一端,rutime bound同static unbound有着完全不同的形式。而static unbound和runtime unbound则可以用同一种形式表达。
这样的话,如果要使得一门语言具备较理想的gp形式,只需提供static unbound和runtime unbound两种机制,并且是两者具备相同的形式。而runtime bound则可以作为static unbound的副产品存在,任由使用者选择。

On Nov 28, 2007 2:16 PM, 莫华枫 <longsh...@gmail.com> wrote:

莫华枫

unread,
Nov 28, 2007, 1:36:36 AM11/28/07
to pon...@googlegroups.com
这里还要考虑心理因素。面对这个常数倍,不少程序员很自然的会选择小的那个。(包括我在内:))。尽管性能大幅提高,但是相比之下,使用bound不是能够更快吗?
这样的程序员过去很多,所以c++对性能那么敏感。今后当然会越来越少。但除非这类程序员不再把持基础系统的开发,否则无法让人们真正地接受unbound形式。而要让他们屈服,也只有让这个常数倍足够小。

pongba

unread,
Nov 28, 2007, 1:43:38 AM11/28/07
to pon...@googlegroups.com
On Nov 28, 2007 2:36 PM, 莫华枫 <longsh...@gmail.com> wrote:
这里还要考虑心理因素。面对这个常数倍,不少程序员很自然的会选择小的那个。(包括我在内:))。尽管性能大幅提高,但是相比之下,使用bound不是能够更快吗?

我倒是无所谓。性能这个东西要看相对的。如果两者都能满足性能要求,那么好的那个也就是锦上添花,而不是雪中送炭。经济学中的边际效应递减也就是这个意思。
此外,为了获得这个性能就必须有所牺牲,用static bound毕竟有麻烦的地方,不然也不会有那么多人觉得ruby实在用得爽。当两者都能满足性能要求的话,就要看用static bound多付出的那部分编程开销值不值得带来的性能好处了。
还有,据说,把一个优雅的程序效率调上去要比把一个效率高的程序调优雅容易得多:P
 
这样的程序员过去很多,所以c++对性能那么敏感。今后当然会越来越少。但除非这类程序员不再把持基础系统的开发,否则无法让人们真正地接受unbound形式。而要让他们屈服,也只有让这个常数倍足够小。
文化问题。总会改变的。虽然有惯性,但从更大的时间尺度上,适者生存是永恒的真理:)

pongba

unread,
Nov 28, 2007, 1:45:35 AM11/28/07
to pon...@googlegroups.com


On Nov 28, 2007 2:43 PM, pongba <pon...@gmail.com> wrote:
此外,为了获得这个性能就必须有所牺牲,用static bound毕竟有麻烦的地方,

比如C++中的极重要的一个enabling技术——type erasure,就是为了弥补静态和动态之间的鸿沟。boost.function若是拿动态语言实现,根本不费吹灰之力。

莫华枫

unread,
Nov 28, 2007, 2:00:33 AM11/28/07
to pon...@googlegroups.com
好吧好吧,这些我都承认。:P
就是不太情愿直眉瞪眼地等着强大的cpu来解救我们,要是能够让马儿不吃草不是更好吗。再不然,少吃点也行啊。:)
有一点我完全认同,全本unbound应该是我们的目标,static也好runtime也好。不能干等着一切都解决。总会有牛人会想办法来满足我们的。dynamic_cast不也给搞成O(1)得了吗?


On Nov 28, 2007 2:43 PM, pongba < pon...@gmail.com> wrote:

Atry

unread,
Nov 28, 2007, 3:26:56 AM11/28/07
to pon...@googlegroups.com
可是 Boost.Function 若用 D 实现也很容易。主要是因为 C++ 没有可变模板参数,换句话说就是 C++ 的编译时泛型还不能方便的描述足够"泛"的情况,而不是编译时泛型本身不可行。

静态类型语言有一个好处很多错误不必到运行的时候才发现,编译的时候的类型检查能节省一部分运行时调试的时间。从逻辑上说,不管那些类型是编译时检查还是运行时检查,程序员的大脑在运行以前就应该已经知道那个类型(或 Concept 或 Interface)到底是什么,能做什么。

在07-11-28,pongba <pon...@gmail.com> 写道:

buhongbo

unread,
Nov 28, 2007, 8:07:01 PM11/28/07
to pon...@googlegroups.com
看你们的讨论,真牛!
我有个弱弱的疑问:你们考虑语言的时候,似乎忘记了编译器这位幕后英雄!
编译器的实现技术对于这些所谓好的抽象和并发能够支持到多大程度?
我觉得一个语言的抽象能达到什么程度是不是还和编译器有关啊?
听说Smalltalk的编译运行速度非常的慢。
------------------
buhongbo
2007-11-29

-------------------------------------------------------------
发件人:Atry
发送日期:2007-11-28 16:27:45
收件人:pon...@googlegroups.com
抄送:
主题:[TopLanguage] Re: C++的抽象惩罚中,有多少是因为强调性能引发的

寒光

unread,
Nov 28, 2007, 8:29:10 PM11/28/07
to TopLanguage
在我看来,大家所讨论的好像就是要建立一种 无类型 系统的语言
所有的类型都是运行时推断的
听说这是自然语言最开始的目标,C语言之前的B语言就是这样的,它们认识如:
a = 10;
b = "abc";
然后知道a是整形,b是字符串,但也许是基于当时的条件,最终还是C取代了B
能够从开始就确定的事情为什么非要等到运行时确定?
又有多少东西是非要等到运行才能确定的?

寒光

unread,
Nov 28, 2007, 8:29:20 PM11/28/07
to TopLanguage

chenxiaoshun

unread,
Nov 29, 2007, 12:09:13 AM11/29/07
to TopLanguage
我有两个问题:
1、能不能简单地解释一下什么是"接口的侵入性"?
2、"实际上,接口整个儿就是向效率妥协的产物。"这个不对吧,抛开效率不谈,接口本身也具备明确的语意。

On 11月28日, 下午1时57分, pongba <pon...@gmail.com> wrote:
> 实际上,接口整个儿就是向效率妥协的产物。为了能够迅速地多态调用对象上的方法,接口被做成侵入性的,这样当目标类在编译的时候便能够遵循接口制定的二进制契约(虚函数表),而调用方也将依赖接口制定的二进制契约。如果接口被做成非侵入性的,那么编译器编译目标类的时候便不能知道该建立什么样的二进制布局让调用方来遵循,而只能靠名字查找来动态绑定方法了。
>
> 接口以后肯定会成为非侵入性的,实际上接口的侵入性很大程度上影响了语义表达,进而影响了复用性。(为什么要有适配器模式?)
>
> On Nov 28, 2007 1:36 PM, pongba <pon...@gmail.com> wrote:
>
>
>
> > 哎呀,一不小心又把静态类型写成强类型了。
> > 纠正,是静态类型,不是"强类型"。
>
> > On Nov 28, 2007 1:36 PM, pongba <pon...@gmail.com> wrote:
>
> > > 1. 类型安全性是建立在强类型的基础上的。而强类型的重点目的之一便是效率(生成高效的代码)。
> > > 2.
> > > template未必需要完整的信息来获得类型安全性,只需要concept即可。有了concept把关,在template的实现层面便可以完全type-check。而在调用层面,concept则可以作为一道运行期(乃至编译期----如果调用参数的类型信息较全(而不是一个光秃秃的object)的话)的contract来把关,也没有太大问题。
>
> > > On Nov 28, 2007 1:32 PM, 莫华枫 <longshank...@gmail.com> wrote:
>
> > > > 但这只是template问题的一半啊,静态非绑定同时也为了获得类型安全性。性能不是全部原因啊?
>
> > > > On Nov 28, 2007 1:25 PM, pongba <pon...@gmail.com > wrote:
>
> > > > > C++实现GP的机制是template,template是在用(代码)空间换(运行)时间。ruby的GP机制duck-typing则是真正直观的GP。
> > > > > template的问题在于它不是运行时非绑定的,即:
>
> > > > > template<typename T>
> > > > > void f(T t ) { t.mem_f(); }
>
> > > > > 这里的mem_f在编译期就已经绑定了,因为编译器必须知道t的类型T。
>
> > > > > 如果不依赖于t的类型,只依赖于动态绑定的话,就像ruby的:
>
> > > > > void f(t) { t.mem_f(); }
>
> > > > > template的静态特性使得比如说我们无法建立一个"存储了满足某一特定concept的所有对象的容器":
>
> > > > > vector<Plugable> v;
>
> > > > > 其中Plugable是一个concept。这是不可能的。
> > > > > C++中传统的解决办法是把Plugable做成一个接口,然后使用适配器设计模式(这是为了弥补接口的侵入性缺陷)。
>
> > > > > 在Ruby的duck-typing里面,要存放任一满足特定concept的对象易如反掌,直接存就可以了。
>
> > > > > On Nov 28, 2007 1:14 PM, 莫华枫 <longshank...@gmail.com > wrote:
>
> > > > > > 求值顺序和序列点问题这我明白,但是template为什么是为了性能折中?
>
> > > > > > On Nov 28, 2007 12:54 PM, pongba <pon...@gmail.com> wrote:
>
> > > > > > > 这个问题我曾经想过,不幸的是,C++中的所有非平凡的语言设计折衷全都是为了性能。
> > > > > > > 最典型的当然是template的设计。最不典型的估计是求值顺序和序列点问题。
>
> > > > > > > On Nov 28, 2007 8:52 AM, 莫华枫 < longshank...@gmail.com> wrote:
>
> > > > > > > > 昨晚上想到这样一个问题:
> > > > > > > > C++的抽象惩罚中,有多少是因为强调性能引发的?有没有不是由于性能造成的?如果有的话是那些?原因是什么?
> > > > > > > > 更进一步,c++的各种缺陷中,有多少是因为强调性能造成的?...
>
> > > > > > > > --
> > > > > > > > 反者道之动,弱者道之用
> > > > > > > > m...@seaskysh.com
> > > > > > > > longshank...@gmail.com
> > > > > > > >http://blog.csdn.net/longshanks/
>
> > > > > > > --
> > > > > > > 刘未鹏(pongba)|C++的罗浮宫
> > > > > > >http://blog.csdn.net/pongba
> > > > > > > TopLanguage
> > > > > > >http://groups.google.com/group/pongba
>
> > > > > > --
> > > > > > 反者道之动,弱者道之用
> > > > > > m...@seaskysh.com
> > > > > > longshank...@gmail.com
> > > > > >http://blog.csdn.net/longshanks/
>
> > > > > --
> > > > > 刘未鹏(pongba)|C++的罗浮宫
> > > > >http://blog.csdn.net/pongba
> > > > > TopLanguage
> > > > >http://groups.google.com/group/pongba
>
> > > > --
> > > > 反者道之动,弱者道之用
> > > > m...@seaskysh.com
> > > > longshank...@gmail.com

pongba

unread,
Nov 29, 2007, 1:25:42 AM11/29/07
to pon...@googlegroups.com
On Nov 29, 2007 1:09 PM, chenxiaoshun <csbchen...@gmail.com> wrote:
我有两个问题:
1、能不能简单地解释一下什么是"接口的侵入性"?
2、"实际上,接口整个儿就是向效率妥协的产物。"这个不对吧,抛开效率不谈,接口本身也具备明确的语意。

1. 侵入性就是指,一个类如果要实现一个接口,就必须修改其定义(并伴随重编译)。而不能通过在"外部"进行指定。
例如:

class A { public: void push(); };

如果以后要实现IStack,就必须修改(侵入)A的定义。

class A : IPushable {...};

实际上这个侵入性真的必要吗?考虑C++0x的concept做法:

concept_map Pushable<A> { }

这个就不会侵入A的定义。

2. 是的,接口有语义。我的意思是,要实现接口语义,可以用侵入性的办法,也可以用非侵入性的办法。使用侵入性的办法是向效率折衷(这在以前当然是必要的,但我预测以后会消失)。我没说接口这个概念没用啊。

pongba

unread,
Nov 29, 2007, 1:27:07 AM11/29/07
to pon...@googlegroups.com

无类型的语言是走极端。历史已经一定程度上证明过了。
类型信息的三大主要作用:1. 帮助编译器生成高效代码。2. 早期纠错。3. 使代码中含有更多的文字(语义)信息。

莫华枫

unread,
Nov 29, 2007, 1:37:58 AM11/29/07
to pon...@googlegroups.com
C++0x中可以这样:
auto a=10;
auto b="abc";
然后知道a是整型,b是字符串。重要的是,这是编译期的类型决断,无需等到运行期。其他语言也都向这个方向发展。
随着编程技术的发展,编译器能够获得的信息越来越多,那么越来越多的东西可以在编译期确定,而只有那些无法在编译期确定的东西,才需要运行期决断。过去,计算机的计算能力有限,那么为了性能,不得不抛弃那些需要运行期决断的技术。但将来随着计算能力的大幅提升,无需过多担心运行期成本,从而放弃那些更灵活更强大的抽象机制。我想pongba就是这个意思。

On Nov 29, 2007 9:29 AM, 寒光 <gmz...@gmail.com> wrote:

Jian Wang

unread,
Nov 29, 2007, 9:04:54 AM11/29/07
to pon...@googlegroups.com
C++的一个重要问题是整数运算时无法得知是否发生溢出,这个算不算为性能妥协?
要跨平台实现整数溢出的判断真是让人焦头烂额。
理想状态是发生溢出时抛出异常。
能用#pragma开关来控制也是不错的方案。


在 07-11-29,莫华枫<longsh...@gmail.com> 写道:

pongba

unread,
Nov 29, 2007, 9:24:36 AM11/29/07
to pon...@googlegroups.com
这个当然算是向性能妥协了:-) 而且就是一个抽象漏洞。

oldrev

unread,
Nov 29, 2007, 9:39:39 AM11/29/07
to pon...@googlegroups.com
说起这个来,我想起一个脑筋急转弯:

智力测验:
int a = 0;
unsigned b = 0;
auto x = a + b;
typeof(x) = ?

在 2007-11-29四的 14:37 +0800,莫华枫写道:

--
"Live Long and Prosper"
- oldrev

莫华枫

unread,
Nov 29, 2007, 7:01:46 PM11/29/07
to pon...@googlegroups.com
ada这方面做的就很好。在Dr.Dobb上还看到过在c++里模拟checked type的。

On Nov 29, 2007 10:04 PM, Jian Wang <oxygen.j...@gmail.com> wrote:

up duan

unread,
Nov 30, 2007, 1:29:42 AM11/30/07
to pon...@googlegroups.com
我感觉不是这样的。
什么是抽象?为什么这叫抽象漏洞?
这很明显只是C++不进行运行时检查导致的问题而已。所有的运算是否溢出都必须在运行时进行检查才知道,而C++[包括C]的特点就是尽可能小的运行时,甚至很多人都说C不需要运行时[当然其实是需要的,不过确实很小罢了]。
说是性能妥协勉强可以接受,但是显然C/C++的骨子里就是这样的体质,就是希望寄托于程序员,就是用这样的不安全性换取性能最大化。

这个当然算是向性能妥协了:-) 而且就是一个抽象漏洞。

pongba

unread,
Nov 30, 2007, 1:35:36 AM11/30/07
to pon...@googlegroups.com


On Nov 30, 2007 2:29 PM, up duan <fix...@gmail.com> wrote:
我感觉不是这样的。
什么是抽象?为什么这叫抽象漏洞?
抽象的目的是简化编程,把程序员隔离于底层实现之上。
举个例子,int这个抽象就有漏洞,会溢出。我们脑子里所认知的"整数"这个抽象概念会溢出吗?
再来,浮点数(float,double)也是抽象,但也会溢出,而且还不精确。我们脑子里所认知的"有理数"抽象有这个问题吗?
一个抽象有漏洞的话,迟早就会掉进去。比如,前阵子闹腾的Excel显示浮点数错误——当一个数非常接近某个临界值的时候就会显示错误(然而内部表示却是正确的)。大嘴Joe和Good Math/Bad Math blog都介绍了这个问题。 

这很明显只是C++不进行运行时检查导致的问题而已。所有的运算是否溢出都必须在运行时进行检查才知道,而C++[包括C]的特点就是尽可能小的运行时,甚至很多人都说C不需要运行时[当然其实是需要的,不过确实很小罢了]。
说是性能妥协勉强可以接受,但是显然C/C++的骨子里就是这样的体质,就是希望寄托于程序员,就是用这样的不安全性换取性能最大化。
为性能妥协,那妥协的另一方是什么?正是抽象的完备性啊。 妥协的结果是什么?是抽象有漏洞啊。

up duan

unread,
Nov 30, 2007, 1:48:55 AM11/30/07
to pon...@googlegroups.com
那也没有看到现在的主流语言采用数学上的Integer概念而不是short int long这类有漏洞的抽象啊。你能说出来几个没有抽象漏洞的语言?
当然,如果你用XSD来顶缸,我没有办法,但对我来说,语言[计算机程序设计语言]一定要是可实现的。

pongba

unread,
Nov 30, 2007, 1:52:10 AM11/30/07
to pon...@googlegroups.com


On Nov 30, 2007 2:48 PM, up duan <fix...@gmail.com> wrote:
那也没有看到现在的主流语言采用数学上的Integer概念而不是short int long这类有漏洞的抽象啊。你能说出来几个没有抽象漏洞的语言?
当然,如果你用XSD来顶缸,我没有办法,但对我来说,语言[计算机程序设计语言]一定要是可实现的。

没错啊。可实现。Python的整型就是无限精度的。
但主流语言大多还是用int/long这些,就是为效率妥协抽象啊。我要说明的意思是,除了int/long这类为效率进行的妥协,还有大量其他语言特性也是如此。
然而,每个妥协带来的效率益处大小不一。如果说目前int/long这种妥协还属必要的话,那么不久template这种妥协也许就不必要了。具体问题具体分析。不代表所有为效率妥协的抽象都是利大于弊的。

Atry

unread,
Nov 30, 2007, 2:35:18 AM11/30/07
to pon...@googlegroups.com
template 不仅仅是为了效率,还为了类型安全。脚本语言用字符串解耦合的火星人类型系统的缺点不光是性能,还有类型安全。
能在编译时检查类型显然有助于错误更早发现。

在07-11-30,pongba <pon...@gmail.com > 写道:

pongba

unread,
Nov 30, 2007, 2:40:49 AM11/30/07
to pon...@googlegroups.com
其实ruby只要加上concept机制,就可以同样得到类型安全(实现端完全类型检查,调用端部分静态检查)。未必一定要是静态类型才能有类型安全的。

我怀疑静态类型系统的根本驱动力还是效率。虽然还有类型安全和文本信息两个好处,但比起效率这个动因来,只有效率才是那个不可妥协的因子。在那个时代背景下,只有选择了静态(无论是全部(C++)还是部分(jAVA)),才得以胜出。

chenxiaoshun

unread,
Nov 30, 2007, 2:49:34 AM11/30/07
to TopLanguage
明白了,谢谢:)你原文用"整个儿"加"就是",让我有点迷糊。

On 11月29日, 下午2时25分, pongba <pon...@gmail.com> wrote:

莫华枫

unread,
Nov 30, 2007, 3:17:25 AM11/30/07
to pon...@googlegroups.com
我觉得问题可以倒过来理解。
有了concept之后,便有机会把静态和动态的unbound多态统一在一个模型下。而runtime bound则是他们的特例。在我们编程的时候,一般都可以用静态的。但在另一些情况下,需要运行时决断。此时则可以使用runtime unbound,而不是矫揉造作的rutime bound。但在concept这个模型下,runtime和static unbound都统一在一种形式下,无需我们操心到时候该用什么。
比如,vector<>里面用具体的类型实例化,就是static unbound;用concept实例化,就是runtime unbound。一切都是自然而然,顺理成章,无需我们多费心机。
然而,对这些"理想抽象"产生阻碍的,是性能。smalltalk有runtime unbound,性能不好,为人们所唾弃。但是为什么人们接受了ruby?技术没有大的进步,只是计算能力提高了,使得人们对runtime unbound的性能损失忍耐度提高了。(这一点我已经证明过了)。
类型安全算不上问题,因为runtime unbound会查询类型的接口,校验接口匹配,并且链接。(实际上计算能力都消耗在这种检验上了)。
现在,如果二进制concept加入,那么可能会大幅提升runtime unbound性能,进一步提高runtime unbound的实用性。
unbound同bound真正的差别在于,bound在编译时进行类型检验,而unbound则在运行时。这应该是不得不付出的代价。

up duan

unread,
Nov 30, 2007, 5:58:39 AM11/30/07
to pon...@googlegroups.com
templete是妥协,但根本不是性能的妥协,而是为了实现静态类型[我指的是编译时类型检查]并且不愿意付出一个类型推导系统而作的妥协,它只是认为由程序员指定类型比由编译器推导类型更划算而已。

至于动态类型[我只得是运行时类型检查],这跟静态类型并不是具有多好的可比性的东西,因为立场不同,怎么说都是见仁见智的事。不能说templete就是跟动态类型[或者晚绑定]有什么妥协之处。

up duan

unread,
Nov 30, 2007, 6:05:10 AM11/30/07
to pon...@googlegroups.com
实际上,单纯的静态类型是不完善的。有很多检查只能留在运行时进行。单纯的动态类型就是完善的。但是,由于我们期望快速的知道我们所犯的错误,并且期望减少运行时类型检查所付出的代价,我们还是需要静态类型检查。从逻辑上讲,动态类型检查永远比静态类型检查的性能低。所以,类型系统必定是静态和动态结合的。
Reply all
Reply to author
Forward
0 new messages