program language

1. 什么是编程语言

编程语言是程序员与设备的交流工具(communication)

目前在工业界和学术界仍是一个非常活跃的领域,例如

编程语言是计算机科学最主要的基础领域之一,一门语言就是一个概念世界(Alan Perlis),例如面向对象与函数式编程。

通过学习编程技巧,可以写出更好的代码、可靠的代码。而理解编程的本质:在于思考。了解编程语言的历史 ,你会发现历史总是在重复。

2. 我们关心什么

  1. 学习成本

    语言设计上:易懂的语法、清晰的语义。

    生产效率上:设计模式。

  2. 使用性能

    编译器优化、垃圾回收(GC)、并行。

  3. 软件质量

    类型安全性、静态/动态类型检测、程序验证。

3. 语言评价准则

可读性要好,阅读起来接近人的思维,理解起来快。包括如下几点

  1. 整体简单性

    C++ 的加 1 操作有如下几种,混搭使用反而就没了整体简单性。编程的时候,每一个句子尽量简单。

    count = count+1;
    count += 1;
    count ++;
    ++ count;
    
  2. 语法反应语义

    语言的形式应该贴近语言的实际意思。在 C 语言中,保留字 static 的意义取决于所出现的位置

    • 函数中定义变量:变量是静态创建的,存储在静态区。
    • 函数外定义变量:变量是文件内可见的。

可写性要好 ,这体现了解决特定问题的程序是否容易创建。例如数学建模用 matlab 来解决,说明 matlab 可写性好。可写性包括如下几点

  1. 简单性和正交性

    较少的基本结构和一套组合基本结构的一致规则(即正交性),简单来说就是利用少量材料就能搭建一个富丽堂皇的大厦。

  2. 对抽象的支持

    过程抽象:子程序实现排序算法,使用时只需要调用函数,而不需要理解算法思想。

    数据抽象:用结构 node 表示二叉树的节点,而不用考虑节点内的结构。

  3. 表达简捷

    count++count+1 简捷。

    计数循环时,for 比 while 方便。

可靠性要有 。保证该语言设计的程序任何情况下都能按设计的那样执行

  1. 类型检查

    一个好的语言应该有完善的类型检查。大致分为静态类型检查(编译时检查)和动态类型检查(运行时检查)。

  2. 异常处理

    这要编译器和解释器提供强大的异常处理:拦截运行时错误的措施。

    例如:除零错误、缓冲区溢出错误。

  3. 尽量别用别名

    别名:两个或者多个不同的名称访问同一个内存单元。

    别名很危险,C语言就提供的指针就是一个危险特性,非高手少用。

    安全语言 rust 提出所有者概念,一个内存单元只有一个所有者。

  4. 可读性和可写性也属于可靠性

    程序越容易编写,出错的可能性越小。

    难以读懂的程序,也难以编写和修改。

学习成本越低越好 ,包括如下几点

  1. 熟悉该语言需要的时间
  2. 编程实现一款软件的成本
  3. 编译执行程序的成本
  4. 编译器的成本(matlab 要收费)
  5. 改需求的成本
  6. 维护软件的成本

其他特性 ,每一种热门语言都有自己的优势特性

  1. 可移植性

    Java 是可移植的,因为各平台都有对应的虚拟机。C 语言需要在不同的平台进行重新编译,所以 C 语言也可以算可移植的。

  2. 普遍性

    C 语言是一种通用的语言,下可用于系统开发,上可用于应用程序开发。

  3. 定义良好性

    Java 有良好的官方定义文档,有了文档,学习都轻松多了。

这里我用一张表格来说明语言的评价准则,可以看出可写性包含可读性,可靠性包含可写性。

特性 可读性 可写性 可靠性
简单性
正交性
数据类型
语法设计
对抽象的支持  
表达  
类型检查    
异常处理    
有限地使用别名    

4. 语言的分类

对计算过程的多种不同看法,产生了不同的计算模型(范型,Paradigms)。基于不同计算范型产生了不同的语言类。主要范型有如下几种

  1. 过程式语言(命令式语言)

    例如 C 语言。将多个指令包装成一个过程(定义过程),用一个过程来描述状态到状态的变化。

  2. 函数式语言

    例如 Lisp 语言。将计算看成对数据的函数变换,语言提供各种函数组合机制。

  3. 面向对象语言

    例如 C++ 、 JAVA 和 JavaScript 。将计算看成是一批独立对象相互作用的效果。面向对象语言提供

    • 描述对象及其行为的机制。(数据成员和函数)
    • 描述对象之间相互作用的机制。
  4. 声明式语言

    例如 constraint language。只描述做什么,不描述怎么做。

  5. 脚本语言

    例如 shell、python、php 。从操作系统命令语言和文本处理语言发展起来的一类语言。

    • 提供了一批高级数据结构,提供灵活的变量、函数、对象等机制。
    • 采用解释方式实现,使用灵活方便。
    • 许多脚本语言提供了高级的文本处理功能。

当然还有一些其他比较小众或易学的语言,例如

5. 语言目标与权衡

不同设计目标导致了不同的语言。

  1. Fortran:高效的大规模数值计算。
  2. Lisp:灵活的符号表达式处理,数据与程序的统一(分布式计算)。
  3. Pascal:结构化程序设计,适用于教学,清晰的基本程序设计概念。
  4. C:系统程序设计,低级操作与高级语言结构的结合。
  5. Smalltalk:概念的统一化和最小化,面向对象
  6. C++:复杂的系统程序设计,低级机制与高级抽象机制(数据抽象的面向对象)的有机融合,支持多种范型的程序设计技术,C++ 最难学,因为容纳了大多数编程语言的特点。
  7. Ada:复杂软件,复杂的嵌入式系统、实时系统
  8. Java:支持面向对象的程序设计,平台无关性,一次编程到处使用,广泛应用于网络环境,有较强的安全性。

只能说,每一个成功的语言都有自己的市场。

6. 语言的实现:抽象机器

机器语言可看作计算机硬件的抽象。计算机硬件生产商会提供一套机器语言给上层使用,即使硬件做了很多优化或者修改,只要保证机器语言不变,那么用这套机器语言设计的程序就可以继续运行。

高级语言可看作是抽象机器语言的一种语言。因为毕竟机器语言(或汇编语言)太少也太难记。

简单地说:实现一种语言,就是在一台抽象机上做出另一台抽象机,用一台已有的抽象机去模拟另一台需要实现的抽象机的行为。

常用的实现方式:编译和解释。

  1. 编译

    将程序翻译成机器语言。例如 C++ 。

  2. 解释

    对程序进行解释执行。五翻译,执行慢,例如 python。

  3. 混合实现

    将程序翻译成中间语言,并解释执行。这样做的好处是较小的翻译代价,较快的执行速度。例如 Java。