- 浏览: 2686986 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
为什么OO很恶心
原文: http://www.sics.se/~joe/bluetail/vol1/v1_oo.html
作者:Joe Armstrong
当我第一次知道OOP的概念时,我非常疑惑,但是不知道为啥——它仅仅在感觉上“不对”。
在OOP问世之后变得粉流行(稍后解释为什么),而批评OOP就像“在教堂里咒骂”。
OO成为了每个受尊敬的语言必须具备的一部分。
而当Erlang变得越来越流行时,我们经常问一个问题“Erlang是OO的吗?”
当然正确的答案是“当然不是”——但是我们没有大肆宣扬——我们只是换了种精心设计的说法,Erlang是某种OO但不是真的是。
这时我想起在法国巴黎时IBM的老板在7th IEEE逻辑编程大会上的演讲。
IBM prolog添加了许多OO扩展,当人们问起时他说:“我们的客户想要OO的prolog,所以我们构建了OO的prolog”
我想到了“多么简单,没有良心的疑虑,没有灵魂的搜索,没有‘这是正确的事情’的问题。。。”
为什么OO很恶心
我对OOP的反对原则源自一些基本的概念,我将概述其中一些反对意见。
反对之一——数据类型和方法应该绑定在一起
对象将方法和数据结构绑定在一起成为不可分割的单元。我认为这是基本的错误,因为方法和数据结构属于完全不同的世界。为啥哩?
1,方法做事情。它们是输入和输出。输入和输出的是方法所改变的数据结构。
在大部分编程语言里,方法由命令式语句顺序构建:“做这件事然后那件事。。。”
理解方法首先得理解做事情的顺序(在懒惰函数编程语言和逻辑语言中这个限制被放宽了)
2,数据结构是结构。它们不做任何事情。它们本质上是声明。“理解”数据结构比“理解”方法简单多了。
方法作为黑盒子来转换输入和输出。如果我理解输入和输出,这样我就理解了方法。这并不意味着我可以写这个方法。
方法通常理解为在一个计算系统里用来将数据结构T1转换为数据结构T2的东西。
既然方法和数据结构是完全不同类型的动物,那么将它们锁在一个笼子里就是完全错误的。
2,反对之二——任何东西都必须为对象
考虑“时间”。在OO语言里“时间”也必须是对象。但是在非OO语言里一个“时间”是一个数据结构的实例。
例如,在Erlang里有许多不同类型的时间,它们可以使用类型声明来明确指定:
注意这些定义不属于任何特殊的对象。它们很普遍,并且数据结构表示的时间可以被系统中的任何方法处理。
没有相关联的方法。
反对之三——在一个OOP语言里数据类型定义散布到任意位置
在OOP语言里数据类型定义属于对象。
这样我就不能在一个地方找到所有的数据类型定义。
在Erlang或者C里我可以在一个单独的include文件或数据字典里定义我所有的数据类型。
在一个OOP语言里我不能——数据类型定义散布到任意位置。
让我举一个例子。假设我想定义一个通用的数据结构。通用数据类型是一个数据类型,它在系统中的任意位置出现。
lisp程序员知道,拥有一个较小数量的通用数据类型和在它上面的大量的小方法会更好。
通用数据类型就比如linked list,或者一个array或者一个hash table或者更高级的对象如time或者date或者filename。
在一个OOP语言里我不得不选择一些base对象来在里面定义通用的数据结构,所有其他想使用这些数据结构的对象必须继承该对象。
假设现在我想创建一些“time”对象,那么它应该属于哪个对象呢。。。
反对之四——对象拥有私有状态
状态是所有罪恶的根源。特别是有副作用的方法应该避免。
在编程语言里状态是令人讨厌的,而真实世界里状态却千奇百怪的存在着。
我对我的银行账户的状态很感兴趣,当我从我的账户存钱或取钱时我希望我的银行账户状态成功更新。
既然状态在真实世界里存在,那么编程语言应该提供什么能力来处理状态呢?
1,OOP语言说“将状态隐藏”。状态仅仅通过访问方法来隐藏和可见。
2,传统编程语言(C,Pascal)说状态的可见度由语言的scope规则来决定。
3,纯声明式语言说没有状态。系统的全局状态转移到方法里然后从方法里出来。
类似于monad(函数式编程语言)和DCG(逻辑语言)等机制被用来隐藏状态,这样它们可以像“有没有状态无所谓”一样来编程,但是对系统状态的完全访问是必需的。
OOP语言所选择的“隐藏状态”可能是最坏的选择。
它们不是将状态显示出来并寻找减少状态的坏处的方式,而是将状态隐藏起来。
为什么OO粉流行?
1,原因1——它被认为很容易学
2,原因2——它被认为让代码更易重用
3,原因3——它被大肆宣传
4,原因4——它创建了一个新的软件工业
我看不到原因1和原因2的证据。原因看起来像是技术背后的驱动力。
如果一个编程语言技术如此之差,然后它创建了一个新的工业来解决它自己本身的问题,则它会成为想从中牟利的人的好工具。
这就是OOP背后真正的驱动力。
以及一篇回复:Why "Why OO Sucks" Sucks
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
没有任何模拟,全部是FP的first class的语言特性.
所以我说,OO(传统OO)的根子完全不在语义语法上,而是计算机模型上.
http://erlang-china.org/misc/commentary-on_a-history-of-erlang.html
这篇文档所传达的要义(用 Erlang 构造系统的感觉)是:一大堆并行运行着的有限状态机,各处做一做协议验证,彼此松散耦合,通常大部分的有限状态机都处在休眠状态。
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
所谓的继承不过就是rescursive type罢了
没有任何模拟,全部是FP的first class的语言特性.
所以我说,OO(传统OO)的根子完全不在语义语法上,而是计算机模型上.
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
实际上也可以定义类型。拙文 new 是什么 this 是什么有指出,见 http://blog.csdn.net/inshua/archive/2008/08/06/2776059.aspx。
这个其实不是做不做的到的问题,而是一种观念的问题。
oo 的意思就是,我必须要按这种方式思考,而 fp 语言在一开始是没有这种要求的。
就像我们写汉字一样,比如 “程”字,你可以把“程”字写的“禾”占大半部分,“呈”占小半部分,这是自由的,笔画规则也是允许的,但是最后写出来发现还是“禾”字小点比较好,写起来也快。
这个比喻里,笔画规则是 fp,而哪部分大哪部分小,这种观念性的东西是 ooa,二者并不矛盾。
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
类似你的文章中的Javascript Class是可以达到貌似“定义”类的效果。
function A() {
this.f1 = f1
this.f2 =f2
}
function f1() { }
function f2() { }
这种“Hashtable”方式的对象,比“VTable”对象更加灵活。但是,有几个不足。
一是空间浪费。VTable把函数都整理在一起。多个对象共享同一份VTable。而Hashtable则每个对象都需要指向所有function。当然,可以手工模拟VTable的效果,但是代码就太烦琐了。
二是继承实现的便利性。VTable实现继承更加方便。
OO和FP相比。有模型上的不同,观念的不同。
T1的意思是,没有什么难度的区别。只是一开始接收的模型不同。如果大家一开始都用FP,自然会习惯FP模型。
以前看过一篇文章,一个Lisp程序员写的。文中写道,现代学校都教Java,这个语言太普通,太容易,不足以淘汰不适合做程序员的学生。应该一开始就教SICP,就可以淘汰跟不上的学生。SICP的学生确实是叫苦连天的。可见,OO和FP的难度是有区别的。
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
实际上也可以定义类型。拙文 new 是什么 this 是什么有指出,见 http://blog.csdn.net/inshua/archive/2008/08/06/2776059.aspx。
这个其实不是做不做的到的问题,而是一种观念的问题。
oo 的意思就是,我必须要按这种方式思考,而 fp 语言在一开始是没有这种要求的。
就像我们写汉字一样,比如 “程”字,你可以把“程”字写的“禾”占大半部分,“呈”占小半部分,这是自由的,笔画规则也是允许的,但是最后写出来发现还是“禾”字小点比较好,写起来也快。
这个比喻里,笔画规则是 fp,而哪部分大哪部分小,这种观念性的东西是 ooa,二者并不矛盾。
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
那就是同一回事了,这其实也是 ooa, 大家都是一家人。去找 c 语言决斗吧。
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
你要做出OO的.操作符也很简单
做一个中缀函数就完了
是挺不错,那我要做一个 class, 以便以后 new Person() 呢。
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
你要做出OO的.操作符也很简单
做一个中缀函数就完了
个人感觉。从来没有觉得对象能够表达现实世界的任何东西。对象只能表达编程元素。
能够打包,确实是OO的好处。尤其是带有多态的打包。
打包很简单。C语言、FP语言都可以打包(放到Tuple、Array里面)。
打包是为了啥呢?为啥OO的打包就那么特殊呢?OO打包的特点在于多态。
多态是为了啥呢?是为了 callback 模式形式的重用。也叫做Template模式。
在callback (or template) 重用模式下,OO是无敌王者。
template( callback) { // 这里重用的是template
.....
callback.run(....)
.....
}
可惜,只依靠这一点,并不足以击败FP。FP的函数直接就可以作为参数和返回值,在callback重用模式更有优势。
OO只能依靠来自于C语言的状态(可重复赋值)特性来击败FP。
OO的打包可以很自然地携带数据(有状态),同时具有多态。
FP的打包,可以分为两种。
(1) Funciton本身。这种情况下,callback重用有优势。甚至优于OO对象。但是,携带数据不方便,只能依靠闭包。而闭包是很麻烦,很不直观的。
(2) Tuple, Array里面放数据和函数。这种情况下,callback重用就比较麻烦,必须自己在template函数外部手工替换Tuple中的某一个Function。而不能达到OO多态那样的自然简单效果。
我在第一页提到了 callback 问题,第二页解释了 class 作为打包的模板的意义,我认为这两个例子足以证明 fp 和 oo 在本质上是相通的。
我想其实 oo 的提出主要是基于一种亚里士多德风格的认识论,人类看事物总是采用分类的方法,而这种方法根据历史经验,也是合理的。所以如果我们站在软件工程的角度来理解 oo,就很好理解了。比如我这个socket 收到了包,包长多少多少,完整不完整。用oo来表达很清晰,socket.onReceivePacket packet.length packet.isComplete,组织的很好,很适合在图纸上设计。如果用闭包、turple 等等来表述这些事物,往往成了 len(packet), is_complete(packet),一下子整个世界都没有主动事物了。
从错误控制和知识组织来说,packet.xxx 中,有多少种 xxx,是易于学习和便于控制的,而能有多少个操作 packet 的函数,是完全无法控制的,不知道在哪个模块又会冒出一个操作 packet 的函数来。
比如现在 erlang 用的 module 风格,操作 binary 的有哪些函数,我想谁都搞不清楚。
lisp 语言很不错,但我看 lisp 语言在软件工程中,绝对不如 oo 化了的 js 好用。
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,以目前的计算机模型带给我们的不是更多的便利而是枷锁.目前几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
OO 的好处就是,它把一组(!)状态和一组(!)函数打包在一起,比较适合表达现实世界。同时,oo 提供创建闭包的便捷方法 “类, 继承”等模板性质的语法,这样我们在创建组合数据的时候就方便多啦,好比 lisp 的 cons 语句,变成 (ele1, ele2,ele3,... )后,比直接用 cons 就好用多了。
个人感觉。从来没有觉得对象能够表达现实世界的任何东西。对象只能表达编程元素。
能够打包,确实是OO的好处。尤其是带有多态的打包。
打包很简单。C语言、FP语言都可以打包(放到Tuple、Array里面)。
打包是为了啥呢?为啥OO的打包就那么特殊呢?OO打包的特点在于多态。
多态是为了啥呢?是为了 callback 模式形式的重用。也叫做Template模式。
在callback (or template) 重用模式下,OO是无敌王者。
template( callback) { // 这里重用的是template
.....
callback.run(....)
.....
}
可惜,只依靠这一点,并不足以击败FP。FP的函数直接就可以作为参数和返回值,在callback重用模式更有优势。
OO只能依靠来可重复赋值(有状态)特性来击败FP(C语言也有这个特性,命令语言都有这个特性)。
OO的打包可以很自然地携带数据(有状态),同时具有多态。
FP的打包,可以分为两种。
(1) Function本身。这种情况下,callback重用有优势。甚至优于OO对象。但是,携带数据不方便,只能依靠闭包。而闭包是很麻烦,很不直观的。
(2) Tuple, Array里面放数据和函数。这种情况下,callback重用就比较麻烦,必须自己在template函数外部手工替换Tuple中的某一个Function。而不能达到OO多态那样的自然简单效果。
这几乎是不可能的,前辈从指令顺序执行到搞出指令流水线,就是想让计算机运行得再快一些.
如果要把并发编程的困难从根子上解决,那无非是搞成即使是赋值操作这种语句,都得一次执行完.想当于把现在的多个指令合并为一个,那流水线还有什么用.我们又返回到玩红警坦克一多就看炮弹飞行轨迹的年代?
你没看见月亮,月亮就不存在?
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,目前的计算机模型带给我们带来的不是更多的便利而是更加坚固的枷锁.几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
这几乎是不可能的,前辈从指令顺序执行到搞出指令流水线,就是想让计算机运行得再快一些.
如果要把并发编程的困难从根子上解决,那无非是搞成即使是赋值操作这种语句,都得一次执行完.想当于把现在的多个指令合并为一个,那流水线还有什么用.我们又返回到玩红警坦克一多就看炮弹飞行轨迹的年代?
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,以目前的计算机模型带给我们的不是更多的便利而是枷锁.目前几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
OO 的好处就是,它把一组(!)状态和一组(!)函数打包在一起,比较适合表达现实世界。同时,oo 提供创建闭包的便捷方法 “类, 继承”等模板性质的语法,这样我们在创建组合数据的时候就方便多啦,好比 lisp 的 cons 语句,变成 (ele1, ele2,ele3,... )后,比直接用 cons 就好用多了。
状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.
赋值语句,可能会改变状态(第二次以上赋值的时候)。不过,赋值不应该是I/O。
I/O应该是指:访问本进程内存之外的设备。赋值还是在本进程内存中发生,为什么是I/O呢?
你的意思是说。能够赋值(第二次以上),从而“有状态、有I/O、有副作用”,才是命令语言(包括OO)的本质?
T1 兄的观点这里的各位帅哥都很熟悉了,有状态变化就会有副作用,但对于 oo => 状态变化,我还没领教过。
远不止副作用那么简单,副作用只是冰山一角.这里有一个党指挥枪,还是抢指挥党的问题.
状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.
赋值语句,可能会改变状态(第二次以上赋值的时候)。不过,赋值不应该是I/O。
I/O应该是指:访问本进程内存之外的设备。赋值还是在本进程内存中发生,为什么是I/O呢?
你的意思是说。能够赋值(第二次以上),从而“有状态、有I/O、有副作用”,才是命令语言(包括OO)的本质?
T1 兄的观点这里的各位帅哥都很熟悉了,有状态变化就会有副作用,但对于 oo => 状态变化,我还没领教过。
原文: http://www.sics.se/~joe/bluetail/vol1/v1_oo.html
作者:Joe Armstrong
当我第一次知道OOP的概念时,我非常疑惑,但是不知道为啥——它仅仅在感觉上“不对”。
在OOP问世之后变得粉流行(稍后解释为什么),而批评OOP就像“在教堂里咒骂”。
OO成为了每个受尊敬的语言必须具备的一部分。
而当Erlang变得越来越流行时,我们经常问一个问题“Erlang是OO的吗?”
当然正确的答案是“当然不是”——但是我们没有大肆宣扬——我们只是换了种精心设计的说法,Erlang是某种OO但不是真的是。
这时我想起在法国巴黎时IBM的老板在7th IEEE逻辑编程大会上的演讲。
IBM prolog添加了许多OO扩展,当人们问起时他说:“我们的客户想要OO的prolog,所以我们构建了OO的prolog”
我想到了“多么简单,没有良心的疑虑,没有灵魂的搜索,没有‘这是正确的事情’的问题。。。”
为什么OO很恶心
我对OOP的反对原则源自一些基本的概念,我将概述其中一些反对意见。
反对之一——数据类型和方法应该绑定在一起
对象将方法和数据结构绑定在一起成为不可分割的单元。我认为这是基本的错误,因为方法和数据结构属于完全不同的世界。为啥哩?
1,方法做事情。它们是输入和输出。输入和输出的是方法所改变的数据结构。
在大部分编程语言里,方法由命令式语句顺序构建:“做这件事然后那件事。。。”
理解方法首先得理解做事情的顺序(在懒惰函数编程语言和逻辑语言中这个限制被放宽了)
2,数据结构是结构。它们不做任何事情。它们本质上是声明。“理解”数据结构比“理解”方法简单多了。
方法作为黑盒子来转换输入和输出。如果我理解输入和输出,这样我就理解了方法。这并不意味着我可以写这个方法。
方法通常理解为在一个计算系统里用来将数据结构T1转换为数据结构T2的东西。
既然方法和数据结构是完全不同类型的动物,那么将它们锁在一个笼子里就是完全错误的。
2,反对之二——任何东西都必须为对象
考虑“时间”。在OO语言里“时间”也必须是对象。但是在非OO语言里一个“时间”是一个数据结构的实例。
例如,在Erlang里有许多不同类型的时间,它们可以使用类型声明来明确指定:
-deftype day() = 1..31. -deftype month() = 1..12. -deftype year() = int(). -deftype hour() = 1..24. -deftype minute() = 1..60. -deftype second() = 1..60. -deftype abstime() = {abstime, year(), month(), day(), hour(), min(), sec()}. -deftype hms() = {hms, hour(), min(), sec()}. ...
注意这些定义不属于任何特殊的对象。它们很普遍,并且数据结构表示的时间可以被系统中的任何方法处理。
没有相关联的方法。
反对之三——在一个OOP语言里数据类型定义散布到任意位置
在OOP语言里数据类型定义属于对象。
这样我就不能在一个地方找到所有的数据类型定义。
在Erlang或者C里我可以在一个单独的include文件或数据字典里定义我所有的数据类型。
在一个OOP语言里我不能——数据类型定义散布到任意位置。
让我举一个例子。假设我想定义一个通用的数据结构。通用数据类型是一个数据类型,它在系统中的任意位置出现。
lisp程序员知道,拥有一个较小数量的通用数据类型和在它上面的大量的小方法会更好。
通用数据类型就比如linked list,或者一个array或者一个hash table或者更高级的对象如time或者date或者filename。
在一个OOP语言里我不得不选择一些base对象来在里面定义通用的数据结构,所有其他想使用这些数据结构的对象必须继承该对象。
假设现在我想创建一些“time”对象,那么它应该属于哪个对象呢。。。
反对之四——对象拥有私有状态
状态是所有罪恶的根源。特别是有副作用的方法应该避免。
在编程语言里状态是令人讨厌的,而真实世界里状态却千奇百怪的存在着。
我对我的银行账户的状态很感兴趣,当我从我的账户存钱或取钱时我希望我的银行账户状态成功更新。
既然状态在真实世界里存在,那么编程语言应该提供什么能力来处理状态呢?
1,OOP语言说“将状态隐藏”。状态仅仅通过访问方法来隐藏和可见。
2,传统编程语言(C,Pascal)说状态的可见度由语言的scope规则来决定。
3,纯声明式语言说没有状态。系统的全局状态转移到方法里然后从方法里出来。
类似于monad(函数式编程语言)和DCG(逻辑语言)等机制被用来隐藏状态,这样它们可以像“有没有状态无所谓”一样来编程,但是对系统状态的完全访问是必需的。
OOP语言所选择的“隐藏状态”可能是最坏的选择。
它们不是将状态显示出来并寻找减少状态的坏处的方式,而是将状态隐藏起来。
为什么OO粉流行?
1,原因1——它被认为很容易学
2,原因2——它被认为让代码更易重用
3,原因3——它被大肆宣传
4,原因4——它创建了一个新的软件工业
我看不到原因1和原因2的证据。原因看起来像是技术背后的驱动力。
如果一个编程语言技术如此之差,然后它创建了一个新的工业来解决它自己本身的问题,则它会成为想从中牟利的人的好工具。
这就是OOP背后真正的驱动力。
以及一篇回复:Why "Why OO Sucks" Sucks
评论
53 楼
liusong1111
2008-08-21
inshua 写道
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
Trustno1 写道
没有任何模拟,全部是FP的first class的语言特性.
所以我说,OO(传统OO)的根子完全不在语义语法上,而是计算机模型上.
http://erlang-china.org/misc/commentary-on_a-history-of-erlang.html
jackyz 写道
这篇文档所传达的要义(用 Erlang 构造系统的感觉)是:一大堆并行运行着的有限状态机,各处做一做协议验证,彼此松散耦合,通常大部分的有限状态机都处在休眠状态。
52 楼
Trustno1
2008-08-21
buaawhl 写道
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
所谓的继承不过就是rescursive type罢了
data Window_obj a=Object a|Window a (Object a) |Button a (Window a) |Image_Button a (Button a) class Window_action a where get_type :: a -> String class Image_action a where show_image ::a->IO () instance Window_action Window where get_type (Window a parent)="window" instance Window_action Button where get_type (Button a parent)="Button" ++ get_type(parent) instance Window_action Image_Button where get_type (Image_Button a parent)="Image_Button" ++ get_type(parent) instance Image_action Image_Button where show_image (Image_Button a parent)=......
没有任何模拟,全部是FP的first class的语言特性.
所以我说,OO(传统OO)的根子完全不在语义语法上,而是计算机模型上.
51 楼
buaawhl
2008-08-21
inshua 写道
buaawhl 写道
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
实际上也可以定义类型。拙文 new 是什么 this 是什么有指出,见 http://blog.csdn.net/inshua/archive/2008/08/06/2776059.aspx。
这个其实不是做不做的到的问题,而是一种观念的问题。
oo 的意思就是,我必须要按这种方式思考,而 fp 语言在一开始是没有这种要求的。
就像我们写汉字一样,比如 “程”字,你可以把“程”字写的“禾”占大半部分,“呈”占小半部分,这是自由的,笔画规则也是允许的,但是最后写出来发现还是“禾”字小点比较好,写起来也快。
这个比喻里,笔画规则是 fp,而哪部分大哪部分小,这种观念性的东西是 ooa,二者并不矛盾。
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
类似你的文章中的Javascript Class是可以达到貌似“定义”类的效果。
function A() {
this.f1 = f1
this.f2 =f2
}
function f1() { }
function f2() { }
这种“Hashtable”方式的对象,比“VTable”对象更加灵活。但是,有几个不足。
一是空间浪费。VTable把函数都整理在一起。多个对象共享同一份VTable。而Hashtable则每个对象都需要指向所有function。当然,可以手工模拟VTable的效果,但是代码就太烦琐了。
二是继承实现的便利性。VTable实现继承更加方便。
OO和FP相比。有模型上的不同,观念的不同。
T1的意思是,没有什么难度的区别。只是一开始接收的模型不同。如果大家一开始都用FP,自然会习惯FP模型。
以前看过一篇文章,一个Lisp程序员写的。文中写道,现代学校都教Java,这个语言太普通,太容易,不足以淘汰不适合做程序员的学生。应该一开始就教SICP,就可以淘汰跟不上的学生。SICP的学生确实是叫苦连天的。可见,OO和FP的难度是有区别的。
50 楼
inshua
2008-08-21
buaawhl 写道
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
实际上也可以定义类型。拙文 new 是什么 this 是什么有指出,见 http://blog.csdn.net/inshua/archive/2008/08/06/2776059.aspx。
这个其实不是做不做的到的问题,而是一种观念的问题。
oo 的意思就是,我必须要按这种方式思考,而 fp 语言在一开始是没有这种要求的。
就像我们写汉字一样,比如 “程”字,你可以把“程”字写的“禾”占大半部分,“呈”占小半部分,这是自由的,笔画规则也是允许的,但是最后写出来发现还是“禾”字小点比较好,写起来也快。
这个比喻里,笔画规则是 fp,而哪部分大哪部分小,这种观念性的东西是 ooa,二者并不矛盾。
至于像 java 这样的 oop 语言,它将 oo 贯彻始终,把类视为顶级公民,在处理过程中把闭包搞成了匿名类,但这并不妨碍我们对它的识别。
49 楼
cabernet1976
2008-08-21
JavaEye的很多文章很不错,而我又是只看不说的
我看了这篇文章,我很想说两句:
1. 存在就有其必然性,你不喜欢OOP,很有可能是你了解的还不够深
2. Python、Ruby的作者都是因为对以前用的语言感觉不爽而开发出了新的语言。比较牛逼的做法是,总结出OOP的suck,自己搞一个完美的语言出来证明一下
(JavaEye第一次留言,也许也是最后一次)
over!
我看了这篇文章,我很想说两句:
1. 存在就有其必然性,你不喜欢OOP,很有可能是你了解的还不够深
2. Python、Ruby的作者都是因为对以前用的语言感觉不爽而开发出了新的语言。比较牛逼的做法是,总结出OOP的suck,自己搞一个完美的语言出来证明一下
(JavaEye第一次留言,也许也是最后一次)
over!
48 楼
buaawhl
2008-08-21
inshua 写道
buaawhl 写道
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
function dog(method){ if(method == 'say'){ return function(){ alert('dog dog dog'); } } else if(method == 'look'){ return function(){ alert('还行'); } } } function habadog(method){ if(method == 'look') // 覆盖 look 方法 return function(){alert('漂亮');} else return dog(method) }
闭包是FP语言的一种携带数据的迫不得已的方案。而且,不能“定义”类型,只能动态“产生”类型。
闭包产生类型,不如OO定义类型那么直观和便利。
47 楼
inshua
2008-08-21
buaawhl 写道
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
function dog(method){ if(method == 'say'){ return function(){ alert('dog dog dog'); } } else if(method == 'look'){ return function(){ alert('还行'); } } } function habadog(method){ if(method == 'look') // 覆盖 look 方法 return function(){alert('漂亮');} else return dog(method) }
46 楼
buaawhl
2008-08-21
Trustno1 写道
buaawhl 写道
Trustno1 写道
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
这是Haskekell的类型定义吧。
能不能给一个类型继承的例子。OO多态就是依靠inherit(对于interface叫做implement)来实现的。
比如,两个类型只有一个方法不同,其他方法都是相同的。
45 楼
inshua
2008-08-21
Trustno1 写道
buaawhl 写道
Trustno1 写道
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
那就是同一回事了,这其实也是 ooa, 大家都是一家人。去找 c 语言决斗吧。
44 楼
Trustno1
2008-08-21
buaawhl 写道
Trustno1 写道
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
有了polymorphism,要override干嘛呢?
43 楼
inshua
2008-08-21
Trustno1 写道
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
你要做出OO的.操作符也很简单
做一个中缀函数就完了
引用
~(P,F)=F(p)
P~F()
P~F()
是挺不错,那我要做一个 class, 以便以后 new Person() 呢。
42 楼
buaawhl
2008-08-21
Trustno1 写道
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
从OO的角度来看,上述这些是 Overload (函数参数类型不同)。
OO的多态是override实现的,函数参数类型是一样的。
41 楼
Trustno1
2008-08-21
引用
OO的打包可以很自然地携带数据(有状态),同时具有多态
只要有类型就能做polymorphism,和是否OO,fp没有关系.
比如这样
class Entity a where getPosition :: a -> (Int,Int) getVelocity :: a -> (Int,Int) getAcceleration :: a -> (Int,Int) getColor :: a -> Color getShape :: a -> Shape
data Paddle = Paddle { paddlePosX, paddlePosY, paddleVelX, paddleVelY, paddleAccX, paddleAccY :: Int, paddleColor :: Color, paddleHeight :: Int, playerNumber :: Int }
引用
instance Entity Paddle where
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
getPosition p = (paddlePosX p, paddlePosY p)
getVelocity p = (paddleVelX p, paddleVelY p)
getAcceleration p = (paddleAccX p, paddleAccY p)
getColor = paddleColor
getShape = Rectangle 5 . paddleHeight
你要做出OO的.操作符也很简单
做一个中缀函数就完了
引用
~(P,F)=F(p)
P~F
P~F
40 楼
inshua
2008-08-21
buaawhl 写道
个人感觉。从来没有觉得对象能够表达现实世界的任何东西。对象只能表达编程元素。
能够打包,确实是OO的好处。尤其是带有多态的打包。
打包很简单。C语言、FP语言都可以打包(放到Tuple、Array里面)。
打包是为了啥呢?为啥OO的打包就那么特殊呢?OO打包的特点在于多态。
多态是为了啥呢?是为了 callback 模式形式的重用。也叫做Template模式。
在callback (or template) 重用模式下,OO是无敌王者。
template( callback) { // 这里重用的是template
.....
callback.run(....)
.....
}
可惜,只依靠这一点,并不足以击败FP。FP的函数直接就可以作为参数和返回值,在callback重用模式更有优势。
OO只能依靠来自于C语言的状态(可重复赋值)特性来击败FP。
OO的打包可以很自然地携带数据(有状态),同时具有多态。
FP的打包,可以分为两种。
(1) Funciton本身。这种情况下,callback重用有优势。甚至优于OO对象。但是,携带数据不方便,只能依靠闭包。而闭包是很麻烦,很不直观的。
(2) Tuple, Array里面放数据和函数。这种情况下,callback重用就比较麻烦,必须自己在template函数外部手工替换Tuple中的某一个Function。而不能达到OO多态那样的自然简单效果。
我在第一页提到了 callback 问题,第二页解释了 class 作为打包的模板的意义,我认为这两个例子足以证明 fp 和 oo 在本质上是相通的。
我想其实 oo 的提出主要是基于一种亚里士多德风格的认识论,人类看事物总是采用分类的方法,而这种方法根据历史经验,也是合理的。所以如果我们站在软件工程的角度来理解 oo,就很好理解了。比如我这个socket 收到了包,包长多少多少,完整不完整。用oo来表达很清晰,socket.onReceivePacket packet.length packet.isComplete,组织的很好,很适合在图纸上设计。如果用闭包、turple 等等来表述这些事物,往往成了 len(packet), is_complete(packet),一下子整个世界都没有主动事物了。
从错误控制和知识组织来说,packet.xxx 中,有多少种 xxx,是易于学习和便于控制的,而能有多少个操作 packet 的函数,是完全无法控制的,不知道在哪个模块又会冒出一个操作 packet 的函数来。
比如现在 erlang 用的 module 风格,操作 binary 的有哪些函数,我想谁都搞不清楚。
lisp 语言很不错,但我看 lisp 语言在软件工程中,绝对不如 oo 化了的 js 好用。
39 楼
buaawhl
2008-08-21
inshua 写道
Trustno1 写道
引用
不自量力的提醒一下 T1 兄,OCaml 为 OO 的 Caml,可见 fp 和 oo 是可以兼容的。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,以目前的计算机模型带给我们的不是更多的便利而是枷锁.目前几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
OO 的好处就是,它把一组(!)状态和一组(!)函数打包在一起,比较适合表达现实世界。同时,oo 提供创建闭包的便捷方法 “类, 继承”等模板性质的语法,这样我们在创建组合数据的时候就方便多啦,好比 lisp 的 cons 语句,变成 (ele1, ele2,ele3,... )后,比直接用 cons 就好用多了。
个人感觉。从来没有觉得对象能够表达现实世界的任何东西。对象只能表达编程元素。
能够打包,确实是OO的好处。尤其是带有多态的打包。
打包很简单。C语言、FP语言都可以打包(放到Tuple、Array里面)。
打包是为了啥呢?为啥OO的打包就那么特殊呢?OO打包的特点在于多态。
多态是为了啥呢?是为了 callback 模式形式的重用。也叫做Template模式。
在callback (or template) 重用模式下,OO是无敌王者。
template( callback) { // 这里重用的是template
.....
callback.run(....)
.....
}
可惜,只依靠这一点,并不足以击败FP。FP的函数直接就可以作为参数和返回值,在callback重用模式更有优势。
OO只能依靠来可重复赋值(有状态)特性来击败FP(C语言也有这个特性,命令语言都有这个特性)。
OO的打包可以很自然地携带数据(有状态),同时具有多态。
FP的打包,可以分为两种。
(1) Function本身。这种情况下,callback重用有优势。甚至优于OO对象。但是,携带数据不方便,只能依靠闭包。而闭包是很麻烦,很不直观的。
(2) Tuple, Array里面放数据和函数。这种情况下,callback重用就比较麻烦,必须自己在template函数外部手工替换Tuple中的某一个Function。而不能达到OO多态那样的自然简单效果。
38 楼
Trustno1
2008-08-21
terranhao 写道
这几乎是不可能的,前辈从指令顺序执行到搞出指令流水线,就是想让计算机运行得再快一些.
如果要把并发编程的困难从根子上解决,那无非是搞成即使是赋值操作这种语句,都得一次执行完.想当于把现在的多个指令合并为一个,那流水线还有什么用.我们又返回到玩红警坦克一多就看炮弹飞行轨迹的年代?
你没看见月亮,月亮就不存在?
37 楼
terranhao
2008-08-21
Trustno1 写道
引用
不自量力的提醒一下 T1 兄,OCaml 为 OO 的 Caml,可见 fp 和 oo 是可以兼容的。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,目前的计算机模型带给我们带来的不是更多的便利而是更加坚固的枷锁.几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
这几乎是不可能的,前辈从指令顺序执行到搞出指令流水线,就是想让计算机运行得再快一些.
如果要把并发编程的困难从根子上解决,那无非是搞成即使是赋值操作这种语句,都得一次执行完.想当于把现在的多个指令合并为一个,那流水线还有什么用.我们又返回到玩红警坦克一多就看炮弹飞行轨迹的年代?
36 楼
inshua
2008-08-21
Trustno1 写道
引用
不自量力的提醒一下 T1 兄,OCaml 为 OO 的 Caml,可见 fp 和 oo 是可以兼容的。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
赋值语句的存在和机器环境有关系,假如我采用 erlang 这样的环境来做 oo,那我也可以把赋值语句砍掉(就变成 ets 了,ets 其实也是赋值,只不过将“脏”操作控制在 ets 模块而已)。
我没有说OO和FP不能兼容.
但是OO的在什么条件下能呈现他的好处?这是问题的关键所在.在我看来,以目前的趋势来看,这种条件会越来越弱.
赋值语句的确和机器环境有关系,换而言之,以目前的计算机模型带给我们的不是更多的便利而是枷锁.目前几乎所有的并发编程的困难都由此而来,因此针对这个根子我们从理论上来说就需要从新选择计算模型,在实践上来讲就需要在目前的计算机上构建一个对应的模拟环境.
OO 的好处就是,它把一组(!)状态和一组(!)函数打包在一起,比较适合表达现实世界。同时,oo 提供创建闭包的便捷方法 “类, 继承”等模板性质的语法,这样我们在创建组合数据的时候就方便多啦,好比 lisp 的 cons 语句,变成 (ele1, ele2,ele3,... )后,比直接用 cons 就好用多了。
35 楼
Trustno1
2008-08-21
inshua 写道
buaawhl 写道
Trustno1 写道
引用
无状态虽然在线程调度上是优点。在编程便利性上是缺点。
状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.
赋值语句,可能会改变状态(第二次以上赋值的时候)。不过,赋值不应该是I/O。
I/O应该是指:访问本进程内存之外的设备。赋值还是在本进程内存中发生,为什么是I/O呢?
你的意思是说。能够赋值(第二次以上),从而“有状态、有I/O、有副作用”,才是命令语言(包括OO)的本质?
T1 兄的观点这里的各位帅哥都很熟悉了,有状态变化就会有副作用,但对于 oo => 状态变化,我还没领教过。
远不止副作用那么简单,副作用只是冰山一角.这里有一个党指挥枪,还是抢指挥党的问题.
34 楼
inshua
2008-08-21
buaawhl 写道
Trustno1 写道
引用
无状态虽然在线程调度上是优点。在编程便利性上是缺点。
状态是不是便于编程,与是否有线程没多大关系,Event driven 上我看不出状态有利在那里.很多人恐怕从没有想到过的是,赋值语句实则上就是一种IO(为什么呢?可以仔细的想一想).但凡IO,必定是并发的.这才是OO或者说是命令语言的根子所在.
赋值语句,可能会改变状态(第二次以上赋值的时候)。不过,赋值不应该是I/O。
I/O应该是指:访问本进程内存之外的设备。赋值还是在本进程内存中发生,为什么是I/O呢?
你的意思是说。能够赋值(第二次以上),从而“有状态、有I/O、有副作用”,才是命令语言(包括OO)的本质?
T1 兄的观点这里的各位帅哥都很熟悉了,有状态变化就会有副作用,但对于 oo => 状态变化,我还没领教过。
发表评论
-
ECUG III -- Elrang中国用户组第三次活动
2008-11-06 11:00 2250详情请见: http://ecug.org/ 大家也帮忙宣传 ... -
Erlang内存管理和运行模式笔记
2008-09-25 16:40 5390Erlang进程非常轻量级 进程间通过消息传递进行通讯 进程接 ... -
Erlang:一个通用的网络服务器
2008-09-24 16:50 6144原文: Erlang: A Generalized TCP S ... -
Erlang里的make
2008-09-22 17:38 3745Erlang自带一个make工具 我们看一个例子 目录结构: ... -
介绍Erlang里的Record
2008-09-12 15:52 8588原文: Erlang: An Introduction to ... -
Erlang与ActionScript3采用JSON格式进行Socket通讯
2008-09-02 16:37 6304前提: 需要下载as3corelib来为ActionScrip ... -
Erlang的JSON库
2008-09-02 15:40 9358使用下列JSON库: http://www.lshift.ne ... -
Erlang和ActionScript3的Socket通讯
2008-09-02 13:18 2880server.erl -module(server). ... -
Erlang和Ruby的Socket通讯
2008-09-01 22:12 2320server.erl -module(server). ... -
Erlang实现简单Web服务器
2008-09-01 17:59 5786转贴一个简单的Web服务器: httpd.erl %% h ... -
Mnesia用户手册:五,Mnesia高级特性
2008-09-01 17:27 7056本章描述了构建分布式、容错的Mnesia数据库相关的高级特性: ... -
Mnesia用户手册:四,事务和其他访问上下文
2008-08-29 00:06 6822本章讲述Mnesia事务系统和事务属性,它们让Mnesia成为 ... -
Mnesia用户手册:三,构建Mnesia数据库
2008-08-27 21:46 9234本章详细介绍了设计Mnes ... -
Mnesia用户手册:二,Mnesia快速上手
2008-08-27 14:09 9121本章介绍了Mnesia: 1) ... -
Mnesia用户手册:一,介绍
2008-08-26 15:47 7791Mnesia是一个分布式数据 ... -
OTP Design Principles: Supervisor Behaviour
2008-08-26 00:06 3103Supervisor Behaviour是一个用来实现一个su ... -
gen_event例子:terminal_logger
2008-08-25 16:23 1662定义三个terminal_logger: $$ termina ... -
OTP Design Principles: Gen_Event Behaviour
2008-08-25 16:06 18051,事件处理原则 在OTP里,event manager是一个 ... -
gen_fsm例子:code_lock
2008-08-22 18:35 2139改了一下代码,可以run了: %% code_lock.erl ... -
OTP Design Principles: Gen_Fsm Behaviour
2008-08-22 17:29 18371,有限状态机 FSM,有 ...
相关推荐
《大师品软件_Why Software Sucks》是一本深入探讨软件设计缺陷和用户体验问题的书籍,由David S. Platt撰写。这本书旨在揭示为什么某些软件在使用过程中让人感到困扰,并提出改善软件设计的策略。作者Platt是一位...
Any book is the product of a team effort. In this one, I've had an out- standing supporting cast. Everyone at Addison-Wesley understood and got behind the concept of a book for the users of ...
【itsucks-0.4.1开源爬虫】是一个针对初学者友好的网络爬虫工具,它的出现使得没有编程背景的用户也能轻松进行数据抓取。这个最新版本的itsucks,不仅提供了完整的爬虫功能,还引入了一个简洁的图形化用户界面(GUI...
【itsucks-0.4.1.zip】是一个包含开源Java Web Spider项目的压缩包,这个项目被称为itSucks。itSucks的设计目标是帮助用户轻松构建网络爬虫,它使用了Web机器人技术,允许用户通过定义下载规则来抓取网页内容。项目...
爬虫源码,开源 java 很好 强大 可扩展
信息安全_数据安全_Why_the_role_of_CISO_sucks_and_w 信息安全研究 金融安全 安全人才 安全对抗 法律法规
标题“why-your-test-suite-sucks”暗示了我们讨论的主题是关于测试套件存在的问题以及如何改进它们。测试套件是软件开发过程中的重要组成部分,它确保代码的质量、稳定性和可靠性。然而,当测试套件出现问题时,...
【Atc Sucks-crx插件】是一款针对英文用户的浏览器扩展程序,主要目的是表达用户对“ATC”(可能是某个网站、服务或功能的缩写)的不满情绪。这款插件由开发者创建,用于向用户展示ATC存在的问题,或者提供某种方式...
因此,【Smooth Scroll Sucks-crx插件】致力于让浏览器的滚动条重获自由,释放用户在浏览时可能遇到的困扰。它通过禁用页面上的平滑滚动特效,使鼠标滚轮和触摸板的操作更加直接,使浏览体验更接近传统习惯。 现代...
【Vegandale Sucks-crx插件】是一款专为英文用户设计的浏览器扩展程序,主要功能是替换网络上关于“Vegandale”的相关信息,将其转化为“Gentrified Parkdale”。这款插件针对的是那些可能对“Vegandale”这一名称...
ItSucks 网络爬虫 描述 这个项目是一个具有下载(和恢复)文件能力的java网络蜘蛛(网络爬虫)。 它还可以使用正则表达式和下载模板进行高度定制。 所有后端功能也可在单独的库中使用。 官网 执照 本地开发使用 将 ...
IE SUCKS这么糟糕,实际上是有趣的观看失败! IE样式信息条在页面中的障碍码时发光。 无广告! Internet Explorer是一个浏览器的F ****笑话,并字面上持有进步! 在逐步淘汰之前庆祝最终几天,用IE吸收插件。 每当...
【标题】:“rabbit sucks!-crx插件”是一个针对特定网站或应用的浏览器扩展,其主要功能是优化用户界面,提供更加个性化的浏览体验。这个插件的名称可能具有一定的幽默感,暗示它可以帮助用户摆脱某些他们不喜欢的...
DuPont Sucks FTP(DPS-FTP)是一个开源的FTP客户端工具,专为用户提供便捷的文件传输服务。这个项目的名称“DuPont Sucks FTP”可能源于一种幽默或反讽的表达,暗示它并非由杜邦公司开发,而是由社区驱动的独立项目...
【标题】"kevingreen.sucks" 是一个网站项目,基于 "Simple Next App" 构建,主要用于表达对个人或事物的不满或者批评。在互联网上,".sucks" 域名通常被用来创建一个平台,让人们可以公开讨论他们认为有问题的事物...
使用IE Sucks插件庆祝淘汰前的最后几天。 每当遇到旨在帮助Internet Explorer像老人一样上楼的代码时,我们都会像过去一样发出经典的IE信息栏。 您知道,这意味着您只有更多无用的废话可以破坏您的浏览器,除非这次...
标题中的“sucks:用python制作的小CRUD”表明这是一个使用Python编程语言开发的简单创建、读取、更新和删除(Create, Read, Update, Delete,简称CRUD)应用程序。CRUD是数据库操作的基础,是任何数据管理系统的基石...
【标题解析】:“your-band-sucks-v2”很可能是一个音乐相关的项目或应用,可能是由开发者创建的一个幽默或者讽刺性的音乐分享平台。"v2"表示这是项目的第二个版本,通常意味着在原有基础上进行了改进和优化。 ...
如果您确实讨厌Twitter内的Moments标签,并且在尝试查看通知时始终单击此处,则只需安装此… 如果您确实讨厌Twitter内的Moments选项卡,并且在尝试查看通知时始终单击此处,则只需安装此轻量级扩展程序即可将其发送...