免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 29649 | 回复: 133
打印 上一主题 下一主题

[C] 思考题:语言是工具?重要是思想?那如何表达思想?(修改版) [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-24 19:11 |只看该作者 |正序浏览
本帖最后由 OwnWaterloo 于 2011-10-24 22:34 编辑

标题
懂的同学应该明白,标题既想切题,又想不剧透,真心不好取…… 有什么建议么?

语言
给出一些代码既可以让题目表述更准确,又可以避免一些不必要的分歧,使讨论更集中。
既然这里是C/C++板块,自然用C描述比较合适。 但讨论不一定局限于C/C++。
不是都在追求所谓的语言只是工具么?

背景
与图形相关的程序的一些片段,不妨设

点定义如下:

  1. typedef struct {
  2.       int x,y;
  3. } point;
复制代码
目前程序需要处理圆形与矩形。将来可能会增加更多的需要处理的图形。
定义如下:

  1. typedef struct {
  2.       point  center;
  3.       double radius;
  4. } circle;

  5. typedef struct {
  6.       int top,bottom,left,right;
  7. } rect;
复制代码
两点间距离以及圆形与矩形的中心计算已经实现:

  1. double distance(point p,point q);
  2. point center_of_circle(circle const* c) { return c->center; }
  3. point center_of_rect(rect const* r)
  4. {
  5.       point p;
  6.       p.x = (r->left + r->right)/2;
  7.       p.y = (r->top + r->bottom)/2;
  8.       return p;
  9. }
复制代码
问题1
在思考以下问题的同时请考虑软件演化时可能会需要处理更多的图形。

1.1. 设计一个函数R: double R(? x);
计算图形x的中心到原点的距离

1.2. 设计一个函数D: double D(? x,? y);
计算图形x,y中心之间的距离

1.3. 设计一个函数P: double P(? x,? y,? z);
计算图形x,y,z的中心构成的三角形(假设输入保证构成三角形)的周长


====== ====== 分割线:两个新增问题 ====== ======
原准备另开一贴的, 不过貌似这贴也不挤, 就放这了。


问题2: 设计一个函数 double distance(? x,? y); 求两图形上最近两点之间的距离

例:
若两圆相切或相交,则最近两点(可能存在多对)间距离为0。
若两圆相离,则最近两点是连接两圆心的线段与两圆的的两个交点之间的距离。

  1. double distance_of_circle(circle const* a,circle const* b)
  2. {
  3.       double d = distance(a->center,b->center);
  4.       double s = a->radius + b->radius;
  5.       return d>s? d-s: 0;
  6. }
复制代码
同样,还有矩形与矩形、圆形与矩形的距离计算

  1. double distance_of_rect(rect const* a,rect const* b);
  2. double distance_of_circle_rect(circle const* c,rect const* r);
复制代码
问题3: 设计一个函数 double intersection(? x,? y,? z); 求三图形交集的面积。

论坛徽章:
0
134 [报告]
发表于 2012-07-16 09:59 |只看该作者
有时间好好看一下这帖子。

论坛徽章:
0
133 [报告]
发表于 2012-07-15 10:32 |只看该作者
本帖最后由 KanonInD 于 2012-07-15 11:00 编辑

回复 108# 狗蛋
如果嫌这个还不够刺激的话,人会说话,哑巴是人吗?人有四肢,独臂神尼是人吗?人有心跳,死人能不能告诉我他心

跳3下需要多少时间?

要在面向对象的框架里面解决这个问题,除了让人这个基类什么都不会(因而多态也就成了摆设)之外,恐怕就只能搞

一些诘屈聱牙的东东打补丁了。这也是复杂性爆炸的一个原因。
当然,这问题用接口(speakable)之类,解决起来就很容易了。
但,不同类的speakable实现可能不太一样:比如聋子说话声音会大、还会吐字不清、口型比较夸张。这样如果每个类

都重写speakable的话,继承还有什么作用?
不想重写,难道从聋子和左腿残疾多重继承,以便让一个左腿残疾的聋子说话?嗯嗯,当然,左腿残疾还要从活人继承

——从死人继承的左腿残疾貌似也是不可或缺的:这可关系到“滑落的力学分析”和走路的姿势,其中前者死活都一样

而后者不同……

好吧,咱不玩了好吧?你没崩溃我都要崩溃了……

想让子类缺少父类的某个方法吗?Ruby的开放类可以打开一个现成的类,向其添加、删除、修改其方法,可以将一个现成的类改得面目全非。
例如:
  1. #!/usr/bin/ruby
  2. # -*- coding: utf-8 -*-

  3. class Base
  4.   def method1
  5.     puts "do method1..."
  6.   end

  7.   def method2
  8.     puts "do method2..."
  9.   end
  10. end

  11. class SubClass < Base
  12.   def method3
  13.     puts "do method3..."
  14.   end
  15. end

  16. c = SubClass.new
  17. c.method1
  18. c.method2
  19. c.method3

  20. class SubClass #打开SubClass
  21.   undef method2  # 去除 method2
  22. end

  23. c.method1
  24. c.method2 # method2 已去除,所以出错了。
  25. c.method3
复制代码

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
132 [报告]
发表于 2012-07-15 02:31 |只看该作者
回复 130# captivated

时间有点久了……如果没记错的话,这贴选polymorphism作为例子的动机并不是很纯洁……是个坑……所以你这样我会问心有愧的……

记得当时论坛上又开始OO来OO去了。
所以此帖目的之一是想将一些被OO(或者说被某些语言的OO、这里也包括C++)玩坏了的人吸引进来。
当他们见到自己熟悉的那些东西并为之感到自豪时再用double dispatch泼冷水。
对那些被design pattern玩坏了的、提出visitor pattern的人,再用multiple dispatch继续泼。射一脸。

从结果来看……应该不是没人上当,而是被OO玩坏的人也就只会当那几个口号的复读机,都是战斗力不足5的渣渣。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
131 [报告]
发表于 2012-07-14 19:14 |只看该作者
语言是表述思维的工具

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
130 [报告]
发表于 2012-07-14 19:10 |只看该作者
叔叔觉得有必要将此贴再顶一次...


论坛徽章:
0
129 [报告]
发表于 2012-07-12 14:34 |只看该作者
摘自http://bbs.chinaunix.net/thread-3610928-13-1.html

【狗蛋】
    其实,标准的C库是这样玩的:

HANDLE initRC4(...)  //初始化RC4算法,返回的handle关联于一个结构体

char RC4_iterator(HANDLE h)
{
     unsigned k, byte;
     //do sth with RC4(h)->i and RC4(h)->j and etc..

     return byte
}

一样和算法描述文档一一对应……




当然,coroutine的确还是方便很多的,毕竟不需要像上面一样手工维护一个控制块了。不过这并不说明它就提供了什

么没它就没法实现的功能……

像函数式语言在并行上的优势这类东西,才是其它语言难以取代的——注意这是在机器自动优化方面的优势;传统语言

一样可以写map-reduce。

换言之,函数式语言可以不管你需不需要,只要机器有能力,就并行执行所有可以并行的代码;而传统语言必须自己分

析哪些代码可以并行、并且还得写代码探测当前机器可以提供什么样的并行支持。


这里面很关键的一点是:任何语言的使用者,在关注问题本身之外,都必须关注如何把问题用目标语言表述出来。

在RC4的例子里,c之类语言的使用者在考虑如何表述时,需要额外考虑状态保持问题;而有coroutine的语言则不必考

虑这种问题。

但这并不是不需代价的。因为c语言的使用者只需了解指针和它的32个关键字、48种运算符;有coroutine的语言使用者

则还需要了解额外的yield关键字。
(嗯,或许上面这段话还要加上一个无聊的前缀:除了机器本身之外……)




当然,仅仅一个yield关键字没什么。但关键字更多一些呢?再多一些?
尤其要注意的是,这些关键字并不是独立的。它们必须能够和其它任何关键字、数据类型协同动作,才可能构成可靠的

程序。


比如说,就好像这几天讨论的:c++为何要搞个引用呢?因为它增加了类和运算符重载概念!
而且,有了类,new/delete就是必要的;可是,还有传统数组?new[]和delete[]赶紧来帮个忙!
再如,有了const关键字,把它应用到自定义类对象上如何?不好意思……没法支持,除非你把const写到参数之前、成

员函数声明之后等等几乎所有能想到的地方……而且写在每个地方的精确意义,还各不相同!

显然,一个新特性、一个新关键字的加入,带给一个语言的复杂度,可能是指数级的。





事实上,早在图灵之前,计算机已经有了——不仅有最古老的算盘,还有近代科技的结晶:精密的机械计算器,甚至还

有电子管组成的庞然大物。

可以说,任何被人们充分认识的可靠规律,都可以利用来实现某种计算;而且只要肯动脑筋,哪怕是一两百年前对规律

的认识,都可能足以支持任何计算。

比如说,为了计算特定的某种积分,可以选择特定参数设计合适电路,在输出端挂个仪表测量之;然后通过其它装置,

将仪表读数查表转换成结果:哪种现代计算机可以做的如此简洁?利用现代元器件实现这种东西,哪种现代计算机能达

到同样的效率?

但它们都成不了气候。原因就是:支持通用计算的机器,设计复杂度失控。

所以,图灵之前,只有专用计算器,没有通用计算机。


图灵的贡献,或者说图灵机的优点,不是复杂、晦涩;而是简单。

从此,不再需要什么积分电路、不再需要考虑积分、矩阵等等都该如何支持,只要支持布尔代数即可。



编程语言方面,其实完全一样: 仅仅布尔代数已经足以实现所有功能;但如果加上额外的一些支持,人们做事就会更

加容易。
于是,从布尔代数的与或非三种逻辑、真假两种取值,发展到了存储程序、又到了C的32个关键字、48种运算符;然后

又发展出面向对象、泛型等等新奇玩意儿。


不过,虽然新添加的这些东西,每一样看起来都带来了不少方便;但它们加起来之后,可能就是复杂度失控。

重复一次前面的论断: 伴随着每一个关键字、每一个新特性的加入,都可能导致语言复杂度指数级增长。

或许,32个关键字,普通人不到半年就可以掌握;64个关键字,可能也不过是10年苦读而已;而128甚至256个关键字,

可能就只能寄希望一个长生不老的变态学到宇宙终结了。


反过来说,使用布尔代数编程,虽然没什么不能实现的,但需要考虑的细节太多太多,稍大的程序就会超出人们的能力

范围;这是简化的极端。
使用c编程,可以做的东西和布尔代数一样多,但需要考虑的东西大幅减少,人们这才有能力写必须数百上千甚至几千

行代码才能解决的复杂问题;
而使用c++的全部特性编程,可以做的东西还是和布尔代数一样多;但人们不得不拿出绝大部分的精力去应付它本身的

边边角角,以至于除非限制使用它的一部分特性,否则就不可能写出很大的程序——这当然还不是复杂的极限。


——注意,把程序模块化可以把需要解决的问题分解、独立出来。这些模块综合起来可能超过千万甚至亿万行代码。
——哪怕是布尔代数,在模拟函数机制、然后把问题模块化后,同样可以支持千万行代码。这是模块分解的功劳,和语

言无关。
——所以,上面说c可以写几百几千行的复杂程序,并不是笔误。确切含义是“一个不可分解的复杂问题,在其规模为

几百甚至几千行时,仍然可以被C支持”:当然,这种问题可能并不存在,这里只是为了把模块分解的影响独立出去的

一个思想实验罢了。



c显然并不刚好使得“语言本身的复杂度-工程复杂度”函数取最小值;但可以肯定它极其接近(稍偏复杂);而c++显

然比c更偏复杂一些。python可能比它们两个都更靠近函数曲线的最小值。


lisp等函数系语言,有不同于布尔代数的另一个起点。从这个起点开始设计的编程语言,关联着另外一个“语言本身的

复杂度-工程复杂度”函数。这个函数曲线的最小值可能会比基于图灵机的语言更低,也可能更高,目前尚无法判定。

当然,具体到某个类型的工程上,“语言本身的复杂度-工程复杂度”函数可能非常不同。这使得人们必须根据实际需

要,选择更合适的语族。
但有一点是不变的(也是违背很多人的“常识”的):更复杂的语言可以简化更小的工程,但随着复杂度的增加,它甚

至可能无法支持并不特别复杂的工程。


典型的例子就是c++的模板: 用它来实现某种类型无关的算法,的确比管理一大堆只有参数不同的函数省力;但在它实

现每一个算法时,难度都远大于实现针对特定类型的算法。
这使得它只适合于写重用率极高、但目标较为单一的库。即便如此,这些库,如stl,仍然是如此复杂,以至于对绝大

多数的人来说如同天书——相信即便是它们的作者,排错时也少不得要骂娘。
可是,stl 所实现的,只是平常到不能再平常的一组基本算法而已。


可以肯定,c/python都不是最好的语言。真正取得“语言本身的复杂度-工程复杂度”函数曲线最小值的语言,可能需

要基础理论的突破才有可能,这也正是函数式语言引起关注的根本原因之一;

而c++引入的类、模板等等,至少在这么多年的实践之后,并不能证明它就是增加软件生产力的正确方向。
当然,模板在写库方面,取得的成就是有目共睹的。但这不代表这个方向就是正确的。


————————————————————————————————————————
如果说,结构化编程的成就是“强制划分函数,区分函数和数据结构”的话,面向对象的成就就是“强制划分模块,区

分接口和实现”。
而函数和模块这两个概念,才真正推动了软件工程的发展,简化了编程难度;也只有和函数/模块直接相关的概念,才

值得冒着指数增加语言复杂度的风险添加支持。


现在的乱象,其实是“模块本身被语言支持之后”引起的连锁反应。
或者说,因为模块相关概念的加入,各种语言不得不提供种种便利;这就启动了“关于模块概念的复杂度指数增长过程

”。
而这新添加的一堆堆所谓的便利,大部分是实质的负担;换句话说,那些新语言、新特性,解决的问题往往远比它带来

的更多。

最终,哪些东西更基本、更不可替代,它们才会被保留下来;甚至可能出现真正的、深刻揭示本质的理论,完成类似图

灵机的提炼。
也只有经过这样的简化和提炼,面向对象(或者,面向接口)才可能保证提供的便利远大于麻烦,才有资格取代结构化

编程,才有资格声称自己开创了一个新时代。




【幻の上帝】
回复 105# 狗蛋


控制复杂度是得考虑的。
不过,先入为主地认为因为一个东西复杂就得让位于现有的shit就没那么有趣了。
模版复杂?很正确,不过,generics多少是为nominal typing擦屁股的。如果一开始就少了一堆overloading、

conversion和cast的ranking,写个算法会有多难呢。
>>它们必须能够和其它任何关键字、数据类型协同动作
——这往往是幻想,因为现有的语言结构已经够反紧凑的了。nullptr能和多少东西协作?(哦,这货的存在仍然是为

了给类型系统擦屁股。)这里的指数级,已经打了几个折扣?
我是宁可看到C++加入yield而复杂10倍的,这比chrono、ratio之类甚至threading都有意义得多。
……当然,实际嘛,传统还有现实,你懂的。
>>而函数和模块这两个概念,才真正推动了软件工程的发展,简化了编程难度;也只有和函数/模块直接相关的概念,

才值得冒着指数增加语言复杂度的风险添加支持。
“函数”起这么明显的作用实在有些消极——不就是subroutine和module的耦合?不过我看到不少人学了“函数”之后

好像直接以为subroutine=module了。


【狗蛋】

回复 106# 幻の上帝


    1、赞同取消现有shit;甚至赞同取消一些不是shit但在新特性前面无法兼容的东西。

c++的复杂性,恐怕一大半都在舍不得丢掉C的直观的高效率上面。这些当然不是shit,却成功的把c++变成了史上最复

杂的语言。


    2、随意添加新的东西,复杂度有可能在指数级。这多半是因为新特性和旧的东西不是正交的;甚至新特性本身就

是不正确。

比如,new同时包办了 分配内存 和 初始化 两个动作;在其它语言中,即便如此,new和delete与语言的其它部分仍然

是正交的。也就是说,这个东西,其实是不在乎和其他东西的互动细节的,或者说对其它东西是透明的。

如果语言中的所有概念都达到这个高度,那么它们就是正交的。这样正交的概念多一个还是少一个,都不会有什么影响



但在c++里面怎么就成问题了?原因就是new/delete和传统c类型之间不是正交的: c的数组没有初始化这个概念,而

new要求所有类型都知道自己该如何初始化。所以这里它就不得不过来干预下,于是就衍生出了new[]/delete[]。

这只是个很小的例子。诸如类以及在引入模板后不得不搞的那些类型萃取之类怪异的东东,才是大头。
当然,你可以说是被旧东西拖累的。不过我还是认为,这是由于缺乏远期规划,盲目添加新特性,结果因为与旧特性“

不正交”而导致new[]式复杂度爆炸的典型例子。



并且,引入更多东西,并不仅仅是编译器要头疼。

如,引入类之后,开发者忽然就发现自己要面对“正方形是不是矩形”这样的“微妙”问题;还得考虑“游戏角色要不

要从游戏物品继承”等等乱七八糟的东西(这里真正需要处理的是动画如何实现、对象如何管理、技能逻辑如何解析、

剧本如何解析/执行等等问题:面向对象那一套咋呼并不能解决这个问题,却成功的把人们的视线忽悠到了爪哇国)。

再加上泛型什么的那一大箩筐——这就好像回到了图灵机之前的时代: 人们轻易就可以搞一个“积分电路”以任何其

它机器不能比的速度和简洁程度计算积分;但当需要设计一个庞大的通用机器时,他们麻爪了。

直到图灵出现,此时通用计算机能搞了,在上面写计算积分的程序却又难了。但没有人因此把积分电路找回来。



当然,现在那些新语言新概念还没闹到这个程度,但已经露出了端倪。

以类为例,它仅仅是为了程序设计需要解决的一些特定问题设计,而不是对现实世界或计算机的抽象(图灵机和函数编

程不同,它们是对现实和机器的抽象,并且有严格证明);但在宣传时,却把它们当作对现实的抽象进行宣传——甚至

,或许这些人自己都没意识到这个问题。

换言之,面向对象本身,就和现实世界的抽象不是正交的,就必然要由此导致问题复杂化;甚至设计者自己,都不知道

这东西是对计算机的抽象、还是对现实世界的抽象:说它是什么都可以,可又都不像。

这种混乱甚至达到这样的程度: 面向对象理论不假思索的认为,如果某些东西属于同一个类,或者说满足is-a关系,

那么它们就必须有一样的接口。


嗯,好吧,正方形is a长方形吗?如果是,请告诉我它的长和宽!
如果嫌这个还不够刺激的话,人会说话,哑巴是人吗?人有四肢,独臂神尼是人吗?人有心跳,死人能不能告诉我他心

跳3下需要多少时间?

要在面向对象的框架里面解决这个问题,除了让人这个基类什么都不会(因而多态也就成了摆设)之外,恐怕就只能搞

一些诘屈聱牙的东东打补丁了。这也是复杂性爆炸的一个原因。
当然,这问题用接口(speakable)之类,解决起来就很容易了。
但,不同类的speakable实现可能不太一样:比如聋子说话声音会大、还会吐字不清、口型比较夸张。这样如果每个类

都重写speakable的话,继承还有什么作用?
不想重写,难道从聋子和左腿残疾多重继承,以便让一个左腿残疾的聋子说话?嗯嗯,当然,左腿残疾还要从活人继承

——从死人继承的左腿残疾貌似也是不可或缺的:这可关系到“滑落的力学分析”和走路的姿势,其中前者死活都一样

而后者不同……

好吧,咱不玩了好吧?你没崩溃我都要崩溃了……

不玩多重继承?
退到这里,又失去了面向对象容易扩充的特色,和c已经差不多了。


面向对象设计思路的谬误在于,不是因为一组对象属于同一个类,有了is-a关系,所以就一定有一样的接口;相反,是

一组对象支持一样的接口,我们才可以一般化处理同类的东西。

更准确的说,类并不是一个天然属性,而是基于划分方式或者说关注点不同而不同的临时性定义——无论计算机世界还

是现实世界都是如此。



这和当年的结构化观念是非常不同的:你可以从算法+数据结构开始建模,然后写出的东西和模型一致。而面向对象?

你很喜欢一遍一遍琢磨死人活人瘸子哑巴那一大堆变态的类吗?

当然,建模之后再用面向对象语言写代码还是很惬意的。所以我不反对面向对象语言,只反对面向对象建模,或者说面

向对象的思考方式。



要在强化功能的同时规避这种东西,就是我说的,需要“出现真正的、深刻揭示本质的理论,完成类似图灵机的提炼”

——至于提炼的结果,是基于模块和接口的层次、对现实世界抽象(这很难)并据此抽象设计新语言;或者是基于模块

和接口的层次,对计算机抽象(这相对容易)并设计新语言;或者是凭我浅薄的思想尚摸不到边的某种东西,就说不准

了。

c++正是因为缺乏这种提炼、同时又舍不得丢弃c的遗产,才在各种新语言中首先暴露出复杂性失控问题;而其他新语言

,暴露类似问题可能只是时间问题。
——嗯,像python这样取巧搞什么duck type的可能不会出问题……



    3、结构化编程的口号是 算法+数据结构=程序设计
其中,算法就对应于函数;数据结构则对应于数据类型。

显然,算法是可以重用的。
使用函数/过程区分开一个个完整的算法,这是它们可以重用的前提;至于数据结构,它们是函数/过程处理的对象。这

就是结构化的一切。
如果这都不重要,还有什么重要?


【狗蛋】
回复 108# 狗蛋


    补充: 上面的例子是new关键字和旧类型初始化之间的耦合;还有new运算符和内存分配方式(如栈分配、内存池

等)之间的耦合,这就是所谓的placement new和new运算符重载等概念。

——这类东西,在很多微软式封装或初学者架构中比比皆是。

——它们的共同特点就是:给你一个看似很爽很漂亮的封装;但当你真的去用它时,就会发现自己不得不去窥探这个封

装里面的东西;更恶心的情况是:这种封装往往还会近乎“恶意”的阻止你去接触内在的东西……



嗯嗯,封装不是把不希望别人看到的东西藏起来吗?

我并不这么认为。
封装不是简单的把不希望别人看到的东西藏起来。这样的东西是恶心的微软式封装,它教唆、逼迫使用者去寻找“未公

开的系统调用”之类东西,因为这种不公开的东西往往反而是能不能实现某个功能的前提。
这种现象的原因,是这些模块本质上是基于非正交的模块划分而设计的;而“非正交”这个属性,就决定了该模块本质

上不是独立的,不为它(和其它部分之间)的交互设计特例,就不可能完成期望的功能;而这种特例会破坏封装,于是

不得不将其“未公开”,以保持表面上的光鲜,并期望将来某个时候也可以将其纳入管理(或者说,搞另外一个表面光

鲜的“封装”)。

相反,图灵机、函数式编程,甚至C内部的绝大部分概念都是正交的。

正交的东西才可以独立分析,才可以在学习/使用一个关键字时,完全忘掉其它关键字。这就叫xx概念对其它部分透明



我认为,“对其它部分透明”,是可以“隐藏私有实现”的前提。



很可惜,new对于c++的其它部分显然不是完全透明的。这就是之所以衍生出new[]、operator new、placement new的根

本原因。
当然,这可以说成是“为了兼容c”和“为了兼容c以及用户自定义内存分配模型”而不得不付出的代价。
但,至少new和其它部分不正交并因此导致了几倍的混乱,是不争的事实。

——嗯,之前考虑不够细致,不能准确说出我的确切想法。现在可以尝试说的更确切一些了:关键字/特性的多少或许

并不和复杂度挂钩,但硬生生插进体系的、和其它部分非正交的关键字/特性将导致复杂度指数级增长。

如果可能,就将这种新特性置于考虑范围之外。等到实现时、确认不会引起棘手的side effect前提下,能用就拿来用

,不失为好的选择。
但如果在设计之初就考虑这些东西,就必然不得不去窥探它的内部实现,进而导致诘屈聱牙的东西出现。

这,或许就是c++名为c之超集——c有它都有(且完全兼容毫无额外负担还提供了类型安全等等等等免费午餐),c无它

也有——但市场占有率上反而玩不过c的原因吧。

精彩!精彩!!

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
128 [报告]
发表于 2012-07-12 03:22 |只看该作者

挖个坟...

之前没太注意这帖子, 虽然帖子是 OwnWaterloo 发的. 一开始觉得是太形而上学的讨论, 呵呵.

LS两位让帖子浮起来后, 认真看了各位的讨论, 发现我没有错过这个帖子真是太好了, 各位的发言相当nice, 一些表达(嗯, 也是思想的传达)相当到位, 比看无聊的娱乐八卦精彩很多.

----------------------------------------------------------------------------------

叔叔看完此贴后, 将此贴鉴定为: 精彩帖. {:3_189:}


论坛徽章:
1
天蝎座
日期:2013-12-06 18:23:58
127 [报告]
发表于 2012-07-11 08:32 |只看该作者
有点意思,能扯的不一定会写,会写的不一定能扯

论坛徽章:
0
126 [报告]
发表于 2012-07-11 01:44 |只看该作者
不错不错,很好很好,谢谢分享
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP