编程范式 | 青训营笔记

141 阅读7分钟

编程范式(Programming paradigm)

02.编程语言

02_为什么需要编程语言?

机器是没有灵魂的,它只是工具,而我们程序员则需要传入指令与之沟通,人类将这种指令称之为编程语言

02_机器语言

打开任何一个可执行文件,我们可以看到类似的输入和输出,其中一些是数据,大部分则是机器语言

  • 机器语言根据不同的机器有不同的格式,如:8086指令格式,它分为操作码和操作数

一个语言通常需要介质来承载

image-20230419104703468.png

  • 最早的介质是’打孔纸带‘,类似于织布机的这种机器

image-20230419104738806.png

  • 第一位女程序员---ada

image-20230419104808243.png

  • 近代出现的计算机,它的语言通常是需要线缆和开关来控制的

02_汇编语言

因为如果是直接输入数字的话,会非常难输入,于是后面又出现了汇编语言

汇编语言是采用了字母来代替数字,方便输入,同时不同的字母在不同的机器架构下能转换为不同的数字,也体现了它的可移植性

02_高级语言

提高了可移植性,贴近自然语言,贴近人类的思维,于是这样就出现了编译器的概念。

编译器先把高级语言转为汇编语言,之后再把它转变成更大的机器语言

这样就让我们原本写的源码非常小,但编译之后的代码量则非常大

02_几个典型的高级语言

C/C++

C:"中级语言"过程式语言代表

  • 可对位,字节,地址直接操作(像汇编语言一样)
  • 代码和数据分离倡导结构化编程(除了必要的信息之外保持独立)
  • 功能齐全:数据类型和控制逻辑多样化(指针)
  • 可移植能力强

image-20230419105650503.png

C++:面向对象语言代表(在C语言的基础上增加了对类的支持)

  • C with Classes
  • 继承
  • 权限控制
  • 虚函数
  • 多态

image-20230419105851666.png

Lisp

Lisp:函数式语言代表(另一种流派,完全屏蔽指针和地址的操作)

  • 与机器无关
  • 列表:代码即数据
  • 闭包

image-20230419110018874.png

Javascript

javascript:基于原型和头等函数的多范式语言

  • 过程式
  • 面向对象
  • 函数式
  • 响应式

image-20230419110203086.png

02_总结

image-20230419110401710.png

03_编程范式

image-20230419110457886.png

通过一些程序语言的特性对程序语言进行分类

image-20230419110549808.png

  • 命令式:侧重于程序员如何操作机器改变状态
    • 面向过程:把操作用过程进行分组
    • 面向对象:根据操作和其对应的状态进行分组
  • 声明式:程序员声明想要的结果,而不指明具体的操作
    • 函数式:通过一系列的函数组合来生成逻辑
    • 响应式:通过数据流和应征函数的来表示结果

03_过程式编程

  • 自顶向下(程序设计)

  • 结构化编程(思想)

    我们熟知的算法+数据结构的程序就出现在过程式编程范式下

image-20230419110549808.png

03_自顶向下

image-20230419111443433.png

设计程序时要从顶向下来设计一个程序

03_结构化编程

过程式编程范式主要的贡献是引入了结构化编程的思想

用顺序结构、选择结构、循环结构来替代了早先的go to形式

image-20230419111616177.png

03_JS中的面向过程

image-20230419111844826.png

03_面向过程

问题思考:

面向过程式编程有什么缺点?为什么后面会出现面向对象?

答:

  • 数据与算法关联弱(随着代码量增大,看着会难以理解)
  • 不利于修改和扩充
  • 不利于代码重用

image-20230419112208197.png

03_面向对象编程

  • 封装
  • 继承
  • 多态
  • 依赖注入*

03_面向对象编程-封装

  • 关联数据与算法

image-20230419112449158.png

把数据和算法封装到类中

03_面向对象编程-继承

无需重写的情况下进行功能扩充

image-20230419112600477.png

继承可以使用现有类的所有功能,并且在无需编写原有类的情况下对这些类的功能进行扩充

03_面向对象编程-多态

指一个类实例的相同方法在不同的情况下有不同的表现方式,多态使不同结构的可以共享相同的外部接口,进而达到函数复用

不同结构的可以进行接口共享,进而达到函数复用

image-20230419113043921.png

03_面向对象编程-依赖注入

去除代码耦合

image-20230419113043921.png

image-20230419113043921.png

03_面向对象编程-五大原则

  • 单一职责原则SRP(Single Responsibility Principle)
  • 开放封闭原则OCP(Open-Close Principle)
  • 里式替换原则LSP(the Liskov Subsitution Principle LSP)
  • 依赖倒置原则DIP(the Dependency Inversion Principle DIP)
  • 接口分离原则ISP(the Interface Segregation Principle ISP)

03_面向对象

问题思考:

面向对象编程有什么缺点?为什么我们推荐函数式编程

答:

(这里引用一句话来说明)

image-20230419114015569.png

大概意思就是说:因为面向对象它是通过类来封装数据和操作,但是有时我们只需要一个类的一部分功能,但是我们仍不可避免的需要把整个类引过来,也就是我们没有办法进行细功能的功能导入,同时面向对象这种隐藏数据的特点也带来的先天的缺陷,数据的修改历史完全被隐藏了

03_函数式编程

  • 函数是”第一等公民“
  • 纯函数 / 无副作用
  • 高阶函数 / 闭包

image-20230419114452004.png

JS可以通过配合famdajs这个库来实现函数式编程

image-20230419114623224.png

03_函数式编程-First Class Function

image-20230419114714164.png

03_函数式编程-Pure Function

  • 优势

    • 可缓存
    • 可移植
    • 可测试
    • 可推理
    • 可并行

image-20230419114908355.png

03_函数式编程-Currying(柯里化)

柯里化:利用函数和高阶函数来解决参数传来传去的麻烦,并且可以延迟全部参数的准备工作

不去柯里化 -> 柯里化

image-20230419115231543.png

柯里化的实现也有利用闭包和高阶函数的特性

image-20230419115305875.png

03_函数式编程-Composition

有了组合的概念,可以对代码的一些规则进行优化重写

image-20230419115624508.png

03_函数式编程-Functor

可以当做容器的类型,类型支持对容器内元素进行操作

常见的functor:Array(iterable).map、Promise.then

image-20230419120415565.png

03_函数式编程-Monad

可以去除嵌套容器的容器类型

常见monad:Array.flatMap、Promise.then

image-20230419120704485.png

03_函数式编程-Applicative

直接对两个容器进行操作

image-20230419120802403.png

03_响应式编程

  • 异步 / 离散的函数式编程
    • 数据流
    • 操作符
      • 过滤
      • 合并
      • 转化
      • 高阶

JS结合RxJS工具库可以来实现响应式编程

image-20230419120958223.png

03_响应式编程-Observable

  • 观察者模式
  • 迭代器模式
  • Promise / EventTarget超集*

image-20230419121132874.png

image-20230419121144410.png

03_响应式编程-操作符

响应式编程的"compose"

  • 合并
  • 过滤
  • 转化
  • 异常处理
  • 多播

image-20230419121302917.png

以下就是一个转化操作

image-20230419121311603.png

03_响应式编程-Monad

  • 去除嵌套的Obervable

image-20230419121416826.png

03_总结

image-20230419121510890.png

04.领域特定语言

04.什么是领域特定语言

  • Domain-specific language(DSL):应用于特点领域的语言
    • HTML
    • SQL

  • General-purpose language (通用性语言)
    • C / C++
    • Javascript
    • ...

04.语言运行

lexer: 词法解析器 => 形成短语

parser:语法解析器 => 形成语法树

visit:遍历分析

image-20230419121911580.png

04_lexer

主要是把一些语言切分成有意义的token ,一般通过正则表达式去进行区分

SQL Token分类

  • 注释
  • 关键字
  • 操作符
  • 空格
  • 字符串
  • 字符串
  • 变量

image-20230419122721877.png

image-20230419122732424.png

04_Parser-语法规则

上下文无关语法规则

image-20230419122856263.png

**推导式:**表示非终结符到(非终结符或终结符)的关系

**终结符:**构成句子的实际内容,可以简单理解为词法分析中的token

**非终结符:**符号或变量的有限集合。它们表示在句子中不同类型的短语或子句

04_Parser-LL

**LL: **从左到右检查,从左到右构建语法树

image-20230419123201399.png

04_Parser-LR

**LR:**从左到右检查,从右到左构建语法树

image-20230419123333154.png

image-20230419123344770.png

04_tools

image-20230419123430099.png

04_visitor

image-20230419123521980.png

编程范式总结

image-20230419123558782.png