0.维基百科的定义

        编程语言programming language),是用来定义​​计算机程序​​​的​​形式语言​​​。它是一种被​​标准化​​​的交流技巧,用来向​​计算机​​​发出指令。一种计算机语言让​​程序员​​能够准确地定义计算机所需要使用的数据,并精确地定义在不同情况下所应当采取的行动。

        最早的编程语言是在​​计算机发明​​之后产生的,当时是用来控制​提花织布机​及​​自动演奏钢琴​​​的动作​[1]​​。在计算机领域已发明了上千不同的编程语言,而且每年仍有新的编程语言诞生。很多编程语言需要用​​指令​​​方式说明计算的程序,而有些编程语言则属于​​声明式编程​​,说明需要的结果,而不说明如何计算。


1.语言的构成

1.1 语法:

        一般来说,语法和语义的限制是相互配合的,一个语言的语法限制越强,它的语义限制就可以较弱。

        分类于chomsky文法体系:​

编程语言_复杂度

     



  • Words – the lexical level, determining how characters form tokens;
  • Phrases – the grammar level, narrowly speaking, determining how tokens form phrases;
  • Context – determining what objects or variables names refer to, if types are valid, etc.

由低到高依次为词法、句法、和上下文:

对应的检查程序为:

        词法分析器:检查字符串流,根据词法规则判断字符串正确性,把字符串 断为单词串;

                    其使用的工具一般是基于有限状态机 的词法扫描器,流行的有lex。

        句法分析器:检查单词串,根据标识符来判断组成句子的单词序性是否正确;

                   其使用的工具一般是基于下推自动机 的语法分析器,流行的有Yacc。目前比较流行LL分析法和LR分析法。

        语义分析器:进一步检查合法程序结构的上下文相关(语义)正确性,其目的是验证类型信息,并进行相应的语义处理。

                   语义分析是一个异常复杂的过程,由高级语言到中间代码的实现是使用语义相同性来关联的,可行的方法是语法制导翻译,其基础是语言本身无二义性。

                   这个阶段完成:类型检查、上下文关联分析、程序二义性分析

        Java.Vs.C++: Java是一种上下文无关语言;而C++是上下文有关的。

语法Vs.语义:

        关于Ruby与python:Ruby总是可以用多种方式解决一种问题,可以由多种语法完成一种语义实现;而python只有一种方法完成一种语义实现;从大型方法论上来说,还是歧义小的语言更适合于交流,多义性表达式一种很奢侈的行为。


1.2.数据结构--类型:​

        维基百科定义:类型系统用于定义如何将​​编程语言​​​中的​​数值​​​和​​表达式​​​归类为许多不同的​类型​,如何操作这些类型,这些类型如何互相作用。类型可以确认一个值或者一组值具有特定的意义和目的(虽然某些类型,如抽象类型和函数类型,在程序运行中,可能不表示为值)。类型系统在各种语言之间有非常大的不同,也许,最主要的差异存在于编译时期的语法,以及运行时期的操作实现方式。、

        静态类型系统和动态类型系统:语言可以被分为静态型态系统(statically typed systems),例如​​C++​​和​​Java​​,和动态型态系统(dynamically typed systems ),例如​​Lisp​​,​​JavaScript​​,​​Tcl​​和​​Prolog​​。前者可被进一步分为包含声明型态(manifest type )的语言,即每一个变量和函数的型态都清楚地声明,或type-inferred语言(例如MUMPS,ML)。

        类型检查: 类型检查所进行的检验处理以及实行类型的约束,可发生在​​编译时期​​​(静态检查)或​​运行时期​​​(动态检查)。静态类型检查是在​​编译器​​​所进行​​语义分析​​中进行的。如果一个语言强制实行类型规则(即通常只允许以不丢失信息为前提的自动类型转换)就称此处理为强类型,反之称为弱类型

        与此相关:java、C#、C++、python都是强类型的   其中C++系列又是类型静态绑定的,而python是类型动态绑定的。


1.3.  引用机制和重用

     ​​引用 ​​​的中心思想是必须有一种间接设计储存空间的方法。最常见的方法是通过命名变量。根据不同的语言,进一步的引用可以包括指向其他储存空间的​​指针​​​。还有一种类似的方法就是命名一组指令。大多数程序设计语言使用​​宏​​调用、过程调用或函数调用。使用这些代替的名字能让程序更灵活,并更具重用性。


2. 语言的成长

        计算机语言是计算机可以理解的语言,从问题解决思路人的思维描述到计算机可以执行的语言之间的间距叫做说明间距和语言间距。语言的发展历程便是两种间距不断缩小的过程。       

        语言实现其功用是对问题域进行描述,并完成信息交流,这里信息可以表示为语义。

        解决问题的基础是对问题描述的无二义性,这就要求语言的发展是遵循翻译无二义性进行的。


        信息和模型的哲学原理:信息的表示状态为模型,而信息的理解必须有通用的规则才高效,因此大量的模型其实由少量的通用规则构建,人的思维框架便是根据少量的通用规则来理解大量的模型。最后大量的面向问题域的程序都可以抽取其中通用的规则,把规则提取出来组成一个框架,便可以利用一种符号来表示另外一种符号,这就是翻译。语言的​一个发展历程​便是不断构建通用翻译器的历程,以功能为导向,以易用性为目的,语言逐渐抽取规则,退化出翻译器,并逐渐接近问题域。


        汇编:冯诺依曼机唯一识别的是机器码,只有bool型语言才是唯一的机器语言;某一机器会有专门的bool语言转换规则,这就产生了最早的语义分析,把特定的bool语言用一种英语助记符来表示,利用助记符来编写程序。编写的程序根据助记符——布尔语言映射字典转化为唯一的机器语言,可以达到相同的执行效果,不会产生语义丢失。

        可分离的前端与后端:解决问题的思路是相同的,而对于不同的机器需要写出不同的汇编程序,是一种极大的体力浪费。为使程序逻辑设计更具有通用性,在计算机发展的某个阶段,科学家发现使用 一种编程语言+面向指定平台语言翻译器 效率远远超出为每一个机器编写程序,这就促使产生了可分离的前端和后端。其后端平台即是独立的高级语言,前端平台是面对特定机器的翻译器——编译器。


        不断分离的平台,由不断发展的平台形态导致语言不断发展。

        摆脱机器的程序编译平台依赖性:导致了高级语言C语言的出现。作为计算机的C语言不仅是一门程序设计语言,它还包括面对各个平台的编译器 ;

        摆脱机器的程序编运行平台依赖性:导致了JAVA语言的出现。java的最终运行代码以一种平台无关字节码的形式运行,这就必然要求其运行平台必须能运行这种字节码。所以作为计算机运行语言的Java语言不仅是一门程序设计语言,它还包括面对各个机器的虚拟机,以及面向虚拟机的编译器;

        摆脱地域的程序运行依赖性:导致了互联网分布式语言的产生,其中Javascript、DCDL 、 Elang 、 Scala语言兴起。当然作为计算机语言的跨地域语言,还包括支持其运行的Javascript虚拟机,以及跨地域的互联网操作系统。


        语言不仅是一种语言,还有支持它实现与运行的配套软件。不过,可以仅从设计语言来分析设计语言,这就有了语言的优劣之分,即使这种优劣之分野只是对于不同的领域而言。


3.程序设计的方法论


        语言的​另外一个发展历程​便是随着计算机可解决问题的复杂度提升而不断发展,以及随之出现的各种妥协。

        大型软件开发的重要过程是降低复杂度,降低复杂度的工程规则为隔离和规范交互。隔离使思考集中,隔离方法有垂直降低复杂度方法,为垂直分层;水平降低复杂度方法,为水平划分模块化。其对应规范交互为上下层的接口和水平交互接口。

        软件工程学:计算机本质上只能做bool运算,随着语言的不断发展,语言模型的描述性增强,随着问题域问题的增大,对应解决问题的软件复杂度不断提升,软件开发必须作为一项工程来处理了。

        软件工程是研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件,以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来的学科。它涉及到​​程序设计语言​​​、​​数据库​​​、​​软件开发工具​​​、​​系统平台​​​、标准、​​设计模式​​等方面。


3.1.从语言的角度来看程序设计:


                面向机器的语言使用流式编程:最主要的控制语句是MoveTo,函数复杂度控制的层次为语句;

                面向过程的语言使用函数编程:Goto语句增加了流式控制的灵活性,随着程序的增加复杂的增加;需要一种层次划分来对复杂度进行控制,这就是函数编程,利用函数对过程进行封装,把复杂程序划分为一层一层的调用,避免了从整个程序的角度对代码进行底层控制。

                优点:面向过程的编程把过程独立出来,把解决问题的方法即算法划分为一个个过程,分层的控制可以分层控制复杂度。

                缺点:整体函数式编程思想不适合大型软件开发:所待解决的问题增大,建立的模型也较为复杂,模块的划分如果以函数为单位则面临着建模划分模块困难。一个巨大的模型也许融合了多线程,多个毫无联系或者有联系的现实实体,过程的错综复杂导致面向过程的程序设计复杂度增加,但其复杂性表现的背后有相似的规律,必须有更高的抽象规则来降低复杂度。

                面向对象的语言使用对象设计:函数的使用对程序进行分层,降低了垂直复杂度。随着面向问题域的程序设计需要增加,模块化设计要求对模块的划分更接近问题域,这就促使了类似于问题域映射的面向对象程序设计方法。


3.2.联系与区别:面向对象设计是过程设计的更高抽象

        函数式编程对过程进行隔离,对函数参数和返回值进行规范,规定标准接口,降低复杂度。从程序运行角度来说,程序是个实体,其生存过程是一个有限状态机的状态转变,过程只是转变的因素,而我们所需要的是状态,其表现为数据,数据的重要性在此时明确显现出来,算法+数据结构是函数式程序设计的精髓。

        只是利用过程水平划分和垂直调用来对复杂度进行分解,忽视了数据的重要性,也面临着降低复杂度的方法性困难。

        面向对象对程序进行更高抽象,对问题域进行建模,设计类和对象体系,对算法和数据结构进行封装隔离,降低了问题域建模的垂直复杂度。类与类之间设计清晰的接口来规范交互,其本质上是外部划分、内部分层的设计方法。面向对象的设计也给了人工智能看起来实现简单的一条路。


        后记:面向对象语言是引用了一种工程学的角度来诠释一种语言,也许它不是降低复杂度的一种最好方法,但是一种非常有效的方法。有支持的声音,必然有反对的声音。

        哲学与世界建模:哲学家企图用通用的方法对世界进行建模,建立了一套哲学的方法论。直到20世界的逻辑学家哥德尔的完备性定理才使用科学的方法进行了方法论正确性的证明,对于面向对象的程序设计方法论是否通用正确,还有待验证。


4.强类型语言的工程优势


        采集观点:

观点一:静态类型语言因为类型强制声明,所以IDE可以做到很好的代码感知能力,因为有IDE的撑腰,所以开发大型系统,复杂系统比较有保障。

观点二:静态语言相对比较封闭的特点,使得第三方开发包对代码的侵害性可以降到很低。动态语言在这点上表现的就比较差,我想大家都有过从网上下载某个JS包,然后放到项目代码里发生冲突的经历。


        增加确定性是降低复杂度的必要方式,强类型语言的确定性从语言上增加了工程底层的确定性,这需要一个开发难度和测试难度的权衡。

        动态类型语言是在运行时确定数据类型的语言,类型错误在运行时检查出来时一种不明智的行为,有错误早发现是明智的。再进一步说,延迟确定类型是为了灵活放弃确定性的一种权宜之计饿,应该尽量少使用。

        从C++和python的编译和调试系统就可以区别出来,C++进行强类型检查使一些逻辑错误在编译时就表现出来,不像python一样许多错误只有到运行时才能体现出来。


后记:因C++为强静态类型性语言,C++序列化比Python较为困难,随后回顾了一下编程语言。算法也有局部性原理,没有最好的算法,对于程序设计语言,也是如此。所以面向不同的领域,要使用不同的语言。面对大型的程序,要注重设计,从分层开始降低软件复杂度,应该是一个成功软件的基础。