免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: OwnWaterloo
打印 上一主题 下一主题

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

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
101 [报告]
发表于 2011-10-26 22:32 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
102 [报告]
发表于 2011-10-27 09:43 |只看该作者
回复 80# OwnWaterloo


    可是,你的题目针对性很强,或者说,你的题目就是明摆着“用微积分来求我吧”,我是对这点很不感冒。

哦,那个我说的是闭包。分析闭包的自由变量。我记错了。

论坛徽章:
2
技术图书徽章
日期:2013-09-04 15:21:51酉鸡
日期:2013-11-01 21:20:20
103 [报告]
发表于 2011-10-27 10:07 |只看该作者
对于coroutine,C也是有对策滴。C创造了lua,怎么不会lua的技能呢。

实现coroutine的库
http://swtch.com/libtask/

讲解coroutine的文章
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

看一看,还是有学习价值的。

论坛徽章:
0
104 [报告]
发表于 2011-10-27 11:31 |只看该作者
嗯嗯是的来看看是嘿嘿。

论坛徽章:
0
105 [报告]
发表于 2011-10-27 13:11 |只看该作者
对于coroutine,C也是有对策滴。C创造了lua,怎么不会lua的技能呢。

实现coroutine的库


讲解corout ...
mirnshi 发表于 2011-10-27 10:07



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


————————————————————————————————————————
如果说,结构化编程的成就是“强制划分函数,区分函数和数据结构”的话,面向对象的成就就是“强制划分模块,区分接口和实现”。
而函数和模块这两个概念,才真正推动了软件工程的发展,简化了编程难度;也只有和函数/模块直接相关的概念,才值得冒着指数增加语言复杂度的风险添加支持。


现在的乱象,其实是“模块本身被语言支持之后”引起的连锁反应。
或者说,因为模块相关概念的加入,各种语言不得不提供种种便利;这就启动了“关于模块概念的复杂度指数增长过程”。
而这新添加的一堆堆所谓的便利,大部分是实质的负担;换句话说,那些新语言、新特性,解决的问题往往远比它带来的更多。

最终,哪些东西更基本、更不可替代,它们才会被保留下来;甚至可能出现真正的、深刻揭示本质的理论,完成类似图灵机的提炼。
也只有经过这样的简化和提炼,面向对象(或者,面向接口)才可能保证提供的便利远大于麻烦,才有资格取代结构化编程,才有资格声称自己开创了一个新时代。

论坛徽章:
0
106 [报告]
发表于 2011-10-27 13:42 |只看该作者
回复 105# 狗蛋


控制复杂度是得考虑的。
不过,先入为主地认为因为一个东西复杂就得让位于现有的shit就没那么有趣了。
模版复杂?很正确,不过,generics多少是为nominal typing擦屁股的。如果一开始就少了一堆overloading、conversion和cast的ranking,写个算法会有多难呢。
>>它们必须能够和其它任何关键字、数据类型协同动作
——这往往是幻想,因为现有的语言结构已经够反紧凑的了。nullptr能和多少东西协作?(哦,这货的存在仍然是为了给类型系统擦屁股。)这里的指数级,已经打了几个折扣?
我是宁可看到C++加入yield而复杂10倍的,这比chrono、ratio之类甚至threading都有意义得多。
……当然,实际嘛,传统还有现实,你懂的。
>>而函数和模块这两个概念,才真正推动了软件工程的发展,简化了编程难度;也只有和函数/模块直接相关的概念,才值得冒着指数增加语言复杂度的风险添加支持。
“函数”起这么明显的作用实在有些消极——不就是subroutine和module的耦合?不过我看到不少人学了“函数”之后好像直接以为subroutine=module了。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
107 [报告]
发表于 2011-10-27 17:09 |只看该作者
回复 102# starwing83

可就这样都还有许多人看不懂呢

论坛徽章:
0
108 [报告]
发表于 2011-10-27 19:12 |只看该作者
回复 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、结构化编程的口号是 算法+数据结构=程序设计
其中,算法就对应于函数;数据结构则对应于数据类型。

显然,算法是可以重用的。
使用函数/过程区分开一个个完整的算法,这是它们可以重用的前提;至于数据结构,它们是函数/过程处理的对象。这就是结构化的一切。
如果这都不重要,还有什么重要?


至于模块,核心是内部状态和对外接口;接口实现可大可小,小可只管提供自己风格的实现,大可声明自己遵循什么协议,便于第三方对协议编程。

论坛徽章:
0
109 [报告]
发表于 2011-10-28 10:04 |只看该作者
思想呢还是需要语言来表达。但偶认为语言是无法完全表达思想的,也有可能语言表达了另外的东西。

这是语言的 言不尽意 和 言外之意 的功效。 不过有的人,有思想,他不一定要自己表达,如果有人

理解他的思想表达出来了,也挺好。 总之,思想是哲学层面的,语言是技术层面的。现实的世界,两者

都需要,如果单有思想而缺乏技术,只能陷入高深莫测的玄谈,这就是中国哲学的境况。

PS:其实大多数人都是庸人,没啥思想,得过且过,实用至上。

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
110 [报告]
发表于 2011-10-28 10:08 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP