编程范式 | 青训营笔记

137 阅读7分钟

一、编程语言

编程语言是一种用于创建计算机程序的形式化语言。它们被用来定义数据结构、算法和控制流程,以便让计算机执行特定的任务。常见的编程语言包括C、Java、Python、JavaScript、Ruby等。每种编程语言都有其优缺点和适用范围。选择编程语言通常要考虑到项目需求、开发环境、开发人员技能水平等多个因素。

  • 机器语言

计算机能够直接执行的一种二进制代码,由0和1组成。机器语言是计算机的基础语言,可以实现计算机最底层的操作。

  • 汇编语言

机器语言的一种助记符表示方法,使用简单易懂的符号来代替机器语言的二进制指令,使得程序员能够更容易地编写程序。汇编语言需要通过汇编器将代码转换成机器语言才能被计算机执行。

  • 中级语言

面向对象编程语言或者面向过程编程语言,例如C、C++、Java等。中级语言相对于汇编语言和机器语言而言,语法更加高级、更加丰富,可以大幅提高程序员的开发效率。

  • 高级语言

相对于低级语言(机器语言和汇编语言)而言的,包括各种编程语言,比如Python、JavaScript、PHP等。高级语言有更加抽象和高层次的语法和语义,让程序员能够更加方便快捷地编写程序,而且具有跨平台性,同一份高级语言程序可以在不同计算机系统上运行。

二、编程范式

1.过程式

面向过程编程(Procedural Programming):一种基于步骤执行的程序设计范式。面向过程编程的特点是按照一定的顺序,从头到尾依次执行程序代码中的语句,以达到完成特定任务的目的。

优点是可读性强,易于理解和维护;

缺点是扩展性较差,难以应对复杂场景。

2.面向对象

面向对象编程(Object-Oriented Programming,简称OOP)是一种程序设计范式,它使用“对象”作为程序的基本单元,通过封装、继承和多态等机制,实现代码的复用和灵活性。

优点是可扩展性好,能够方便地应对复杂场景;

缺点是学习成本高,代码量大。

3.函数式编程

函数式编程(Functional Programming)是一种基于函数计算的编程范式,它将计算过程看作是函数之间的组合,并强调避免状态和可变数据。

优点是代码简洁清晰、易于理解和调试,适合并行化处理;

缺点是在处理状态和IO时效率不及面向对象编程。

4.响应式编程

响应式编程(Reactive Programming)是一种面向数据流和变化传播的编程范式。它通过将异步数据流和事件进行组合,使得应用程序能够以更加简洁、直观、可维护和可扩展的方式实现响应式的行为。

响应式编程的主要特点包括:

  • 数据流:响应式编程基于数据流,将数据看作一个不断变化的流,开发人员可以通过函数式编程的方式对其进行处理。
  • 异步处理:响应式编程通常通过异步方式处理数据流,从而可以快速地处理数据并提升系统的响应性能。
  • 响应式变化:响应式编程强调对数据流的实时响应和变化,通过监测数据流的变化来执行相应的操作。
  • 无锁设计:响应式编程采用无锁设计,避免了多线程访问时的锁竞争问题,提高了系统的并发性能。
  • 声明式编程:响应式编程采用声明式编程的方式,开发人员只需要关注数据流的处理逻辑,而不需要关心具体的实现细节。
  • 可组合性:响应式编程的运算符都是可组合的,可以通过简单的组装形成复杂的数据流处理逻辑,提高了代码的可维护性和可扩展性

除了以上还有逻辑式编程、并发式编程等。

三、构建领域特定语言

构建领域特定语言(Domain-Specific Language,DSL)可以帮助在特定领域内进行编程或者进行特定操作。DSL适用于需要高度专业化的领域,例如金融、医疗、航空等等。DSL的目的是简化编程和操作的流程,同时提高代码的可读性和可维护性。

创建DSL的过程可以分为以下几步:

  1. 确定DSL的使用场景和目标用户群体:DSL的设计应该针对具体的应用场景和目标用户,例如数据分析、游戏开发等。

  2. 定义DSL的语法和语义:DSL的语法应该简洁明了,符合目标用户的习惯和思维模式。同时,DSL的语义也需要清晰明确,避免歧义和误解。

  3. 实现DSL的解释器或编译器:DSL需要一个解释器或编译器来将代码转换成可执行的程序或脚本。解释器通常比较简单,但速度较慢;编译器则需要更多的开发时间,但执行效率更高。

  4. 提供DSL的文档和示例:为了让用户快速上手,DSL需要提供详细的文档和示例。文档应该涵盖DSL的语法、语义、使用方法、注意事项等内容;示例可以帮助用户理解DSL的使用场景和具体实现方式。

在DSL的编译过程中,lexer、tools、parser和visitor都扮演着不同的角色。

  • Lexer:词法分析器,也称为扫描器,主要任务是将DSL源代码转换为一个个Token(记号),方便后续的解析过程。Lexer通常采用正则表达式等方式来进行Token的识别和提取。

  • Tools:工具集,包括各种辅助工具。DSL开发者可以使用它们来帮助创建DSL的各个组件,例如语法规则和生成代码等。

  • Parser:语法分析器,根据语法规则将Token序列转换成语法树。Parser通常采用自顶向下或自底向上两种策略进行语法分析,并且可以使用递归下降、LR、LL等算法。

  • Visitor:访问者模式,用于对语法树进行遍历和处理。Visitor模式通过定义一个访问者接口以及一些具体访问者类来实现,在遍历语法树时可以根据需要执行不同的操作。

创建DSLparser工具的步骤如下:

  1. 确定DSL语言的语法规则:首先,需要分析DSL语言的语法规则,包括关键字、数据类型、运算符、表达式、变量等基本元素,以及它们之间的关系和优先级等。可以通过BNF范式或EBNF范式等形式对其进行描述。

  2. 选择合适的解析器生成工具:根据DSL语言的特点和需要实现的功能,选择合适的解析器生成工具,如ANTLR、YACC、Bison等。这些工具可以自动生成解析器代码,大大减少了手动编写解析器的时间和工作量。

  3. 编写DSL语言的解析器:根据选择的解析器生成工具,编写DSL语言的解析器代码,包括词法分析器和语法分析器两部分。词法分析器负责将输入的DSL文本转换为标记串,语法分析器则将标记串解析成抽象语法树(AST)。

  4. 实现DSL语言的语义动作:在解析器中,还需要实现DSL语言的语义动作,即对解析得到的AST进行处理,生成对应的目标代码或执行相应的操作。例如,对于一条赋值语句,应该将其左侧的变量绑定到右侧的值上,并将其存储到指定的内存地址中。

  5. 编写DSL语言的示例程序:最后,编写一些DSL语言的示例程序,用于验证解析器和语义动作的正确性。这些示例程序应该覆盖DSL语言的不同方面,并且具有一定的复杂度,以便测试解析器和语义动作的性能和稳定性。

四、总结

重新学习了编程范式,系统的学习了编程语言,构建领域特定语言,以及一些没有掌握的知识点,要进行更加深入学习,以及要多加练习DSL工具。