Tag Archives: Language

编程语言漫谈

写在前边:我们知道现有语言的编程范式有:过程式,面向对象,函数式,逻辑式。随着软件工业化程度的普及,以及软件的复杂度越来越高,编程语言的发展历程 也是从最初的过程式(命令式)语言c,发展到以java语言为代表的面向对象编程语言。而逻辑编程语言(以prolog为代表)和函数式语言(lisp系 列)还多用在学术和人工智能领域中。近几年,随着多核,云计算时代的到来。函数式编程语言逐渐浮出水面,最经典的语言以scheme,common- lisp,ml,clojure,go为代表.而且最近的jdk8也逐步加入了functional,closure,lambda等语法,而且 scala的作者也越来越推崇编码者以函数式语言的思维来coding。可见编程语言的发展也是满足时代的变化不断变化着。从其中的发展历程中我们可以看 到:技术的发展都是在围绕着解决“软件的复杂度”这个基本的需求而发展的。

一、 编程语言概述

编程语言是计算机的符号,是人和计算机交流的语言。我们学习一门新的编程语言时,应该观察这门语言的那些特性呢?《SICP》一书的作者列举了一下三点:
* primitive elements. (基本元素)
* means of combination. (组合手段)
* means of abstraction. (抽象手段)
以上3个特性,基本上涵盖了所有编程语言的特性,并且也是一个语言设计者从开始就要考虑的。我对这三点的理解:primitive elements表示语言的基本符号(基本数据类型,关键字等)也就是词法部分。means of combination利用基本元素通过组合的过程构建大型程序的手段,不同的语言提供的组合手段是不同的。means of abstraction表示抽象,抽象是解决软件复杂度的重要手段,让软件的可读性,可扩展,可重复利用等得到提升。下边会从组合元素和抽象手段来对比语言特性。

二、 组合手段

汇编语言:算是最简单的词法和语法形式了,被称作低级语言。汇编器通过直译的过程将汇编代码翻译为native code(cpu指令集)。 提供的primitive elements有:数字,字符,-,+,*,/ , case,if, break, go,指令等基本元素;通过这些元素组合成计算机执行序列符号。
c语言相比汇编语言更高级,让程序员脱离和cpu,寄存器,内存直接打交道的工作,提供了更多的组合手段:比如数组,结构体等数据结构。
java语言自称是面向对象语言,所以比c语言更进一步,通过强大的类型系统手段来组合属性和方法。
go语言和ML语言非常相仿,“接口”,”高阶函数“,”闭包“,”duck type”,”返回多值”,并提供goroutine等来组合。
prolog语言完全是模式匹配的逻辑语言。他的思想基于:世间所有的定理都给予一个最简单的定理推理而来,就像数学的基础是“1+1=2”,然后才能推导出“万有引力”,“相对论”等定律。
lisp方言以s-expression(著名的S表达式)来组合数据和函数。在lisp中不区分数据和函数,一切皆为数据。
题外话:lisp方言是和图灵机的思想一脉相承的,编码的时候完全感受不到计算机体系结构。而其他语言更多的是冯·洛伊曼的计算,存储思想而设计,要么是“堆栈”结构,要么是“寄存器”结构;

三、 抽象手段

从c语言开始,以函数为单元提供了对程序的抽象。这样大大的提高了程序的可复用,模块化等。让团队合作编码也成为可能。
面向对象编程:基本上隐藏了计算机的细节,开发者通过对象来抽象具体业务。但严格意义上来说java也属于imperative-lang的范畴而且都是传值调用。相比来说,python,ruby更面向对象一些,python融合了面向对象和函数式编程范式,更接近自然语言些。
以lisp为代表的函数式语言:以函数为基本和唯一的抽象;common-lisp也基于宏开发了一套object-oriented的编程方式。我比较倾向于函数式编程理念:函数的无副作用(不用考虑线程安全,特别是对于变态的Haskell),高阶函数,闭包,lambda等。

四、 类型系统

大家平时经常会说:javascript是一个弱类型的语言,java语言是强类型的语言。将编程语言从类型系统的角度区分语言也很有趣。一般来说弱类型语言更偏向自然语言一些,语法也很自由活泼些。而现今语言的走势也趋向与弱类型方向.
计算机是结构化很强的,堆栈上一个二进制位的错误就会导致溢出,bus等错误。所以语言层面的自由得益于编译器或者解释器的功劳。比如java,c等语言有很强的编译时类型检测机制,强类型的好处驱使编码人员写出很少有语法,语义错误的代码,对IDE的支持也便捷,是大型技术团队的合作基石。
弱类型语言让我们获取了自由(不需要类型信息),让程序员少敲了许多键盘。自由是有代价的,编译器或解释器中内含类型推理(infer type); (类型推理是利用归一方法,基于上下文中的变量显式类型,操作符,返回值等信息,利用栈和逐渐替换的过程来推到出类型。) 弱类型虽然可以轻松编译通过(或者不需要编译而是解释执行),但也是有类型检查过程的,只是将此过程延迟到运行时了。所以弱类型语言结构化不强,编码时很难确保类型无误,IDE支持较难。但是通过一些分析器可以不断的检测语法,语义错误,相当于达到了强类型语言的IDE效果。近几年语言的方向朝着逐渐脱离计算机体系结构,向自然语言方向在演进,程序员像艺术家一样用代码自由描绘。

五、编译/解释

java语言是解释型还是编译型的呢? 这个很难说,从java source code -> class byte code 的过程式javac编译器的过程。但是byte code 在jvm上执行的过程可能是解释执行也可能是编译执行的。解释型和编译型的内部都遵从编译原理的过程:词法分析-> 语法分析->语义解析 -> 编译器后端-> native code的过程。 但有各自的优点:
解释器:加载code速度快;解释器需要维护运行时上下文等信息。所以加载必要的代码,片段解释执行。但是对于相同的代码都经过编译过程就很多余,造成时间浪费。
编译器:执行速度快。而且编译器后端也更容易优化中间代码,因为优化过程式一个结构化过程:往往需要遍历整个中间代码,整体优化代码,提高运行效率。
runtime:一般来说解释型语言需要在内存维护运行时上下文信息,服务于运行过程中变量的查找,绑定,scope等。 而编译语言基于寄存器堆栈模型执行代码,基本上数据绑定都在栈结构中完成,运行速度稍微快一些;
hotspot-jvm结合了解释和编译的各自优点;最先解释执行过程,如果方法被频繁执行,而且达到热点(hotspot),jvm会启动编译过程,将次代码编译为native-code,然后缓存起来,下一次的调用直接执行即可。hotspot-jvm执行基于堆栈指令bytecode, 这一点也是基于跨平台的考虑而牺牲了寄存器指令; (而基于android操作系统上的dalvik虚拟机是基于寄存器指令的);
所以说,语言的设计往往是一个权衡过程;获取的“自由”越多,”牺牲“也更大。

六、 总结:

最初从图灵为了解决莱布尼茨提出的:是否存在一个通用模型来解决一切计算任务这个命题,发明了图灵机理论。到冯洛伊曼仿真人脑神经元思考过程产生第一台基 于存储器,运算器的计算机ENIAC,至今,计算机硬件技术并没有实质性的变化,只是随着摩尔定律的破灭,人们发展了多级高速缓存,多核,多cpu技术来 支撑越来越大的计算任务。 在这个过程中,随着人们对逻辑学,符号学,算法的不断研究,用来和计算机交互的语言也越来越抽象和丰富。我们通过这个形象的符号来抽象时间和空间,通过这 个形象的符号来解决软件的复杂性问题,通过这个符号来和计算机传达我们的思想。

from:http://tech.youzan.com/programming-language/

王垠:如何掌握程序语言

学习程序语言是每个程序员的必经之路。可是这个世界上有太多的程序语言,每一种都号称具有最新的“特性”。所以程序员的苦恼就在于总是需要学习各种稀奇古怪的语言,而且必须紧跟“潮流”,否则就怕被时代所淘汰。

作为一个程序语言的研究者,我深深的知道这种心理产生的根源。程序语言里面其实有着非常简单,永恒不变的原理。看到了它们,就可以在很短的时间之内就能学会并且开始使用任何新的语言,而不是花费很多功夫去学习一个又一个的语言。

对程序语言的各种误解

学习程序语言的人,经常会出现以下几种心理,以至于他们会觉得有学不完的东西,或者走上错误的道路。以下我把这些心理简要分析一下。

1. 程序语言无用论。这是国内大学计算机系的教育常见的错误。教授们常常对学生灌输:“用什么程序语言不重要,重要的是算法。”而其实,程序语言却是比算法更加精髓的东西。任何算法以及它的复杂度分析,都是相对于某种计算模型,而程序语言就是描述这种计算模型的符号系统。算法必须用某种语言表述出来,通常算法设计者使用伪码,这其实是不严谨的,容易出现推理漏洞。算法设计再好,如果不懂得程序语言的原理,也不可能高效的实现。即使实现了,也可能会在模块化和可扩展性上面有很大问题。某些算法专家或者数学家写出来的程序极其幼稚,就是因为他们忽视了程序语言的重要性。

2. 追求“新语言”。基本的哲学告诉我们,新出现的事物并不一定是“新事物”,它们有可能是历史的倒退。事实证明,新出现的语言,可能还不如早就存在的。其实,现代语言的多少“新概念”不存在于最老的一些语言里呢?程序语言就像商品,每一家都为了拉拢程序员作广告,而它们绝大多数的设计都可能是肤浅而短命的。如果你看不透这些东西的设计,就会被它们蒙蔽住。很多语言设计者其实并不真的懂得程序语言设计的原理,所以常常在设计中重复前人的错误。但是为了推销自己的语言和系统,他们必须夸夸其谈,进行宗教式的宣传。

3. “存在即是合理”。记得某人说过:“不能带来新的思维方式的语言,是没有必要存在的。”他说的是相当正确的。世界上有这么多的语言,有哪些带来了新的思维方式呢?其实非常少。绝大部分的语言给世界带来的其实是混乱。有人可能反驳说:“你怎么能说A 语言没必要存在?我要用的那个库L,别的语言不支持,只能用A。”但是注意,他说的是存在的“必要性”。如果你把存在的“事实”作为存在的“必要性”,那就逻辑错乱了。就像如果二战时我们没能打败希特勒,现在都做了他的奴隶,然后你就说:“希特勒应该存在,因为他养活了我们。”你的逻辑显然有问题,因为如果历史走了另外一条路(即希特勒不存在),我们会过上自由幸福的生活,所以希特勒不应该存在。对比一个东西存在与不存在的两种可能的后果,然后做出判断,这才是正确的逻辑。按照这样的推理,如果设计糟糕的A 语言不存在,那么设计更好的B 语言很有可能就会得到更多的支持,从而实现甚至超越L 库的功能。

4. 追求“新特性”。程序语言的设计者总是喜欢“发明”新的名词,喜欢炒作。普通程序员往往看不到,大部分这些“新概念”其实徒有高深而时髦的外表,却没有实质的内涵。常常是刚学会一个语言A,又来了另一个语言B,说它有一个叫XYZ 的新特性。于是你又开始学习B,如此继续。在内行人看来,这些所谓的“新特性”绝大部分都是新瓶装老酒。很多人写论文喜欢起这样的标题:《XYZ:A Novel Method for …》。这造成了概念的爆炸,却没有实质的进步。

5. 追求“小窍门”。很多编程书喜欢卖弄一些小窍门,教你如何让程序显得“短小”。比如它们会跟你讲 “(i++) –(++i)” 应该得到什么结果;或者追究运算符的优先级,说这样可以少打括号;要不就是告诉你“if 后面如果只有一行代码就可以不加花括号”,等等。殊不知这些小窍门,其实大部分都是程序语言设计的败笔。它们带来的不是清晰的思路,而是是逻辑的混乱和认知的负担。比如C 语言的++ 运算符,它的出现是因为C 语言设计者们当初用的计算机内存小的可怜,而 “i++” 显然比 “i=i+1″ 少2 个字符,所以他们觉得可以节省一些空间。现在我们再也不缺那点内存,可是++ 运算符带来的混乱和迷惑,却流传了下来。现在最新的一些语言,也喜欢耍这种语法上的小把戏。如果你追求这些小窍门,往往就抓不住精髓。

6. 针对“专门领域”。很多语言没有新的东西,为了占据一方土地,就号称自己适合某种特定的任务,比如文本处理,数据库查询,WEB编程,游戏设计,并行计算。但是我们真的需要不同的语言来干这些事情吗?其实绝大部分这些事情都能用同一种通用语言来解决,或者在已有语言的基础上做很小的改动。只不过由于各种政治和商业原因,不同的语言被设计用来占领市场。就学习而言,它们其实是无关紧要的,而它们带来的“学习负担”,其实差不多掩盖了它们带来的好处。其实从一些设计良好的通用语言,你可以学会所有这些“专用语言”的精髓,而不用专门去学它们。

7. 宗教信仰。很多人对程序语言有宗教信仰。这跟人们对操作系统有宗教信仰很类似。其实如果你了解程序语言的本质,就会发现其实完全没必要跟人争论一些事情。某个语言有缺点,应该可以直接说出来,却被很多人忌讳,因为指出缺点总是招来争论和憎恨。这原因也许在于程序语言的设计不是科学,它类似于圣经,它没法被“证伪”。没有任何实验可以一下子断定那种语言是对的,那种是错的。所以虽然你觉得自己有理,却很难让人信服。没有人会去争论哪家的汉堡更好,却有很多人争论那种语言更好。因为很多人把程序语言当成自己的神,如果你批评我的语言,你就是亵渎我的神。解决的办法也许是,不要把自己正在用的语言看得太重要。你现在认为是对的东西,也许不久就会被你认为是错的,反之亦然。

如何掌握程序语言

看到了一些常见的错误心理,那么我们来谈一下什么样的思维方式会更加容易的掌握程序语言。

1. 专注于“精华”和“原理”。就像所有的科学一样,程序语言最精华的原理其实只有很少数几个,它们却可以被用来构造出许许多多纷繁复杂的概念。但是人们往往忽视了简单原理的重要性,匆匆看过之后就去追求最新的,复杂的概念。他们却没有注意到,绝大部分最新的概念其实都可以用最简单的那些概念组合而成。而对基本概念的一知半解,导致了他们看不清那些复杂概念的实质。比如这些概念里面很重要的一个就是递归。国内很多学生对递归的理解只停留于汉诺塔这样的程序,而对递归的效率也有很大的误解,认为递归没有循环来得高效。而其实递归比循环表达能力强很多,而且效率几乎一样。有些程序比如解释器,不用递归的话基本没法完成。

2. 实现一个程序语言。学习使用一个工具的最好的方式就是制造它,所以学习程序语言的最好方式就是实现一个程序语言。这并不需要一个完整的编译器,而只需要写一些简单的解释器,实现最基本的功能。之后你就会发现,所有语言的新特性你都大概知道可以如何实现,而不只停留在使用者的水平。实现程序语言最迅速的方式就是使用一种像Scheme 这样代码可以被作为数据的语言。它能让你很快的写出新的语言的解释器。我的GitHub 里面有一些我写的解释器的例子(比如这个短小的代码实现了Haskell 的lazy 语义)。

几种常见风格的语言

下面我简要的说一下几种常见风格的语言以及它们的问题。

1. 面向对象语言

事实说明,“面向对象”这整个概念基本是错误的。它的风靡是因为当初的“软件危机”(天知道是不是真的存在这危机)。设计的初衷是让“界面”和“实现”分离,从而使得下层实现的改动不影响上层的功能。可是大部分面向对象语言的设计都遵循一个根本错误的原则:“所有的东西都是对象(Everything is an object)。”以至于所有的函数都必须放在所谓的“对象”里面,而不能直接被作为参数或者变量传递。这导致很多时候需要使用繁琐的设计模式(design patterns) 来达到甚至对于C 语言都直接了当的事情。而其实“界面”和“实现”的分离,并不需要把所有函数都放进对象里。另外的一些概念,比如继承,重载,其实带来的问题比它们解决的还要多。

“面向对象方法”的过度使用,已经开始引起对整个业界的负面作用。很多公司里的程序员喜欢生搬硬套一些不必要的设计模式,其实什么好事情也没干,只是使得程序冗长难懂。

那 么如何看待具备高阶函数的面向对象语言,比如Python, JavaScript, Ruby, Scala? 当然有了高阶函数,你可以直截了当的表示很多东西,而不需要使用设计模式。但是由于设计模式思想的流毒,一些程序员居然在这些不需要设计模式的语言里也采用繁琐的设计模式,让人哭笑不得。所以在学习的时候,最好不要用这些语言,以免受到不必要的干扰。到时候必要的时候再回来使用它们,就可以取其精华,去其糟粕。

2. 低级过程式语言

那么是否C 这样的“低级语言”就会好一些呢?其实也不是。很多人推崇C,因为它可以让人接近“底层”,也就是接近机器的表示,这样就意味着它速度快。这里其实有三个问题:

1) 接近“底层”是否是好事?

2)“速度快的语言”是什么意思?

3) 接近底层的语言是否一定速度快?

对于第一个问题,答案是否定的。其实编程最重要的思想是高层的语义(semantics)。语义构成了人关心的问题以及解决它们的算法。而具体的实现(implementation),比如一个整数用几个字节表示,虽然还是重要,但却不是至关重要的。如果把实现作为学习的主要目标,就本末倒置了。因为实现是可以改变的,而它们所表达的本质却不会变。所以很多人发现自己学会的东西,过不了多久就“过时”了。那就是因为他们学习的不是本质,而只是具体的实现。

其次,谈语言的“速度”,其实是一句空话。语言只负责描述一个程序,而程序运行的速度,其实绝大部分不取决于语言。它主要取决于1)算法和2)编译器的质量。编译器和语言基本是两码事。同一个语言可以有很多不同的编译器实现,每个编译器生成的代码质量都可能不同,所以你没法说“A 语言比B 语言快”。你只能说“A 语言的X 编译器生成的代码,比B 语言的Y 编译器生成的代码高效”。这几乎等于什么也没说,因为B 语言可能会有别的编译器,使得它生成更快的代码。

我举个例子吧。在历史上,Lisp 语言享有“龟速”的美名。有人说“Lisp 程序员知道每个东西的值,却不知道任何事情的代价”,讲的就是这个事情。但这已经是很久远的事情了,现代的Lisp 系统能编译出非常高效的代码。比如商业的Chez Scheme 编译器,能在5秒钟之内编译它自己,编译生成的目标代码非常高效。它可以直接把Scheme 程序编译到多种处理器的机器指令,而不通过任何第三方软件。它内部的一些算法,其实比开源的LLVM 之类的先进很多。

另外一些函数式语言也能生成高效的代码,比如OCaml。在一次程序语言暑期班上,Cornell 的Robert Constable 教授讲了一个故事,说是他们用OCaml 重新实现了一个系统,结果发现OCaml 的实现比原来的C 语言实现快了50 倍。经过C 语言的那个小组对算法多次的优化,OCaml 的版本还是快好几倍。这里的原因其实在于两方面。第一是因为函数式语言把程序员从底层细节中解脱出来,让他们能够迅速的实现和修改自己的想法,所以他们能够迅速的找到更好的算法。第二是因为OCaml 有高效的编译器实现,使得它能生成很好的代码。

从上面的例子,你也许已经可以看出,其实接近底层的语言不一定速度就快。因为编译器这种东西其实可以有很高级的“智能”,甚至可以超越任何人能做到的底层优化。但是编译器还没有发展到可以代替人来制造算法的地步。所以现在人需要做的,其实只是设计和优化自己的高层算法。

3. 高级过程式语言

很早的时候,国内计算机系学生的第一门编程课都是Pascal。Pascal 是很不错的语言,可是很多人当时都没有意识到。上大学的时候,我的Pascal 老师对我们说:“我们学校的教学太落后了。别的学校都开始教C 或者C++ 了,我们还在教Pascal。”现在真正理解了程序语言的设计原理以后我才真正的感觉到,原来Pascal 是比C 和C++ 设计更好的语言。它不但把人从底层细节里解脱出来,没有面向对象的思维枷锁,而且有一些很好的设计,比如强类型检查,嵌套函数定义等等。可是计算机的世界真是谬论横行,有些人批评Pascal,把优点都说成是缺点。比如Brain Kernighan 的这篇《Why Pascal is Not My Favorite Programming Language》,现在看来真是谬误百出。Pascal 现在已经几乎没有人用了。这并不很可惜,因为它被错怪的“缺点”其实已经被正名,并且出现在当今最流行的一些语言里:Java, Python, C#, ……

4. 函数式语言

函数式语言相对来说是当今最好的设计,因为它们不但让人专注于算法和对问题的解决,而且没有面向对象语言那些思维的限制。但是需要注意的是并不是每个函数式语言的特性都是好东西。它们的支持者们经常把缺点也说成是优点,结果你其实还是被挂上一些不必要的枷锁。比如  OCaml 和SML,因为它们的类型系统里面有很多不成熟的设计,导致你需要记住太多不必要的规则。

5. 逻辑式语言

逻辑式语言(比如Prolog)是一种超越函数式语言的新的思想,所以需要一些特殊的训练。逻辑式语言写的程序,是能“反向运行”的。普通程序语言写的程序,如果你给它一个输入,它会给你一个输出。但是逻辑式语言很特别,如果你给它一个输出,它可以反过来给你所有可能的输入。其实通过很简单的方法,可以不费力气的把程序从函数式转换成逻辑式的。但是逻辑式语言一般要在“pure”的情况下(也就是没有复杂的赋值操作)才能反向运行。所以学习逻辑式语言最好是从函数式语言开始,在理解了递归,模式匹配等基本的函数式编程技巧之后再来看Prolog,就会发现逻辑式编程简单了很多。

从何开始

可是学习编程总要从某种语言开始。那么哪种语言呢?就我的观点,首先可以从Scheme 入门,然后学习一些Haskell (但不是全部),之后其它的也就触类旁通了。你并不需要学习它们的所有细枝末节,而只需要学习最精华的部分。所有剩余的细节,会在实际使用中很容易的被填补上。现在我推荐几本比较好的书。

《The Little Schemer》(TLS):我觉得Dan Friedman 的The Little Schemer 是目前最好,最精华的编程入门教材。这本书很薄,很精辟。它的前身叫《The Little Lisper》。很多资深的程序语言专家都是从这本书学会了Lisp。虽然它叫“The Little Schemer”,但它并不使用Scheme 所有的功能,而是忽略了Scheme 的一些毛病,直接进入最关键的主题:递归和它的基本原则。

《Structure and Interpretation of Computer Programs | 计算机程序的构造和解释》(SICP):The Little Schemer 其实是比较难的读物,所以我建议把它作为下一步精通的读物。SICP 比较适合作为第一本教材。但是我需要提醒的是,你最多只需要看完前三章。因为从第四章开始,作者开始实现一个Scheme 解释器,但是作者的实现并不是最好的方式。你可以从别的地方更好的学到这些东西。不过也许你可以看完SICP 第一章之后就可以开始看TLS。

《A Gentle Introduction to Haskell》:对于Haskell,我最开头看的是A Gentle Introduction to Haskell,因为它特别短小。当时我已经会了Scheme,所以不需要再学习基本的函数式语言的东西。我从这个文档学到的只不过是Haskell 对于类型和模式匹配的概念。

过度到面向对象语言

那么如果从函数式语言入门,如何过渡到面向对象语言呢?毕竟大部分的公司用的是面向对象语言。如果你真的学会了函数式语言,就会发现面向对象语言已经易如反掌。函数式语言的设计比面向对象语言简单和强大很多,而且几乎所有的函数式语言教材(比如SICP)都会教你如何实现一个面向对象系统。你会深刻的看到面向对象的本质以及它存在的问题,所以你会很容易的搞清楚怎么写面向对象的程序,并且会发现一些窍门来避开它们的局限。你会发现,即使在实际的工作中必须使用面向对象语言,也可以避免面向对象的思维方式,因为面向对象的思想带来的大部分是混乱和冗余。

深入本质和底层

那么是不是完全不需要学习底层呢?当然不是。但是一开头就学习底层硬件,就会被纷繁复杂的硬件设计蒙蔽头脑,看不清楚本质上简单的原理。在学会高层的语言之后,可以进行“语义学”和“编译原理”的学习。

简言之,语义学(semantics) 就是研究程序的符号表示如何对机器产生“意义”,通常语义学的学习包含lambda calculus 和各种解释器的实现。编译原理(compilation) 就是研究如何把高级语言翻译成低级的机器指令。编译原理其实包含了计算机的组成原理,比如二进制的构造和算术,处理器的结构,内存寻址等等。但是结合了语义学和编译原理来学习这些东西,会事半功倍。因为你会直观的看到为什么现在的计算机系统会设计成这个样子:为什么处理器里面有寄存器(register),为什么需要堆栈(stack),为什么需要堆(heap),它们的本质是什么。这些甚至是很多硬件设计者都不明白的问题,所以它们的硬件里经常含有一些没必要的东西。因为他们不理解语义,所以经常不明白他们的硬件到底需要哪些部件和指令。但是从高层语义来解释它们,就会揭示出它们的本质,从而可以让你明白如何设计出更加优雅和高效的硬件。

这就是为什么一些程序语言专家后来也开始设计硬件。比如Haskell 的创始人之一Lennart Augustsson 后来设计了BlueSpec,一种高级的硬件描述语言,可以100% 的合成(synthesis) 为硬件电路。Scheme 也被广泛的使用在硬件设计中,比如Motorola, Cisco 和曾经的Transmeta,它们的芯片设计里面含有很多Scheme 程序。

这基本上就是我对学习程序语言的初步建议。以后可能会就其中一些内容进行更加详细的阐述。

 

转自:http://www.2cto.com/kf/201208/147722.html