编程范式(Programming paradigm)
02.编程语言
02_为什么需要编程语言?
机器是没有灵魂的,它只是工具,而我们程序员则需要传入指令与之沟通,人类将这种指令称之为编程语言
02_机器语言
打开任何一个可执行文件,我们可以看到类似的输入和输出,其中一些是数据,大部分则是机器语言
- 机器语言根据不同的机器有不同的格式,如:8086指令格式,它分为操作码和操作数
一个语言通常需要介质来承载
- 最早的介质是’打孔纸带‘,类似于织布机的这种机器
- 第一位女程序员---ada
- 近代出现的计算机,它的语言通常是需要线缆和开关来控制的
02_汇编语言
因为如果是直接输入数字的话,会非常难输入,于是后面又出现了汇编语言
汇编语言是采用了字母来代替数字,方便输入,同时不同的字母在不同的机器架构下能转换为不同的数字,也体现了它的可移植性
02_高级语言
提高了可移植性,贴近自然语言,贴近人类的思维,于是这样就出现了编译器的概念。
编译器先把高级语言转为汇编语言,之后再把它转变成更大的机器语言
这样就让我们原本写的源码非常小,但编译之后的代码量则非常大
02_几个典型的高级语言
C/C++
C:"中级语言"过程式语言代表
- 可对位,字节,地址直接操作(像汇编语言一样)
- 代码和数据分离倡导结构化编程(除了必要的信息之外保持独立)
- 功能齐全:数据类型和控制逻辑多样化(指针)
- 可移植能力强
C++:面向对象语言代表(在C语言的基础上增加了对类的支持)
- C with Classes
- 继承
- 权限控制
- 虚函数
- 多态
Lisp
Lisp:函数式语言代表(另一种流派,完全屏蔽指针和地址的操作)
- 与机器无关
- 列表:代码即数据
- 闭包
Javascript
javascript:基于原型和头等函数的多范式语言
- 过程式
- 面向对象
- 函数式
- 响应式
02_总结
03_编程范式
通过一些程序语言的特性对程序语言进行分类
- 命令式:侧重于程序员如何操作机器改变状态
- 面向过程:把操作用过程进行分组
- 面向对象:根据操作和其对应的状态进行分组
- 声明式:程序员声明想要的结果,而不指明具体的操作
- 函数式:通过一系列的函数组合来生成逻辑
- 响应式:通过数据流和应征函数的来表示结果
03_过程式编程
-
自顶向下(程序设计)
-
结构化编程(思想)
我们熟知的算法+数据结构的程序就出现在过程式编程范式下
03_自顶向下
设计程序时要从顶向下来设计一个程序
03_结构化编程
过程式编程范式主要的贡献是引入了结构化编程的思想
用顺序结构、选择结构、循环结构来替代了早先的go to形式
03_JS中的面向过程
03_面向过程
问题思考:
面向过程式编程有什么缺点?为什么后面会出现面向对象?
答:
- 数据与算法关联弱(随着代码量增大,看着会难以理解)
- 不利于修改和扩充
- 不利于代码重用
03_面向对象编程
- 封装
- 继承
- 多态
- 依赖注入*
03_面向对象编程-封装
- 关联数据与算法
把数据和算法封装到类中
03_面向对象编程-继承
无需重写的情况下进行功能扩充
继承可以使用现有类的所有功能,并且在无需编写原有类的情况下对这些类的功能进行扩充
03_面向对象编程-多态
指一个类实例的相同方法在不同的情况下有不同的表现方式,多态使不同结构的可以共享相同的外部接口,进而达到函数复用
不同结构的可以进行接口共享,进而达到函数复用
03_面向对象编程-依赖注入
去除代码耦合
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_面向对象
问题思考:
面向对象编程有什么缺点?为什么我们推荐函数式编程
答:
(这里引用一句话来说明)
大概意思就是说:因为面向对象它是通过类来封装数据和操作,但是有时我们只需要一个类的一部分功能,但是我们仍不可避免的需要把整个类引过来,也就是我们没有办法进行细功能的功能导入,同时面向对象这种隐藏数据的特点也带来的先天的缺陷,数据的修改历史完全被隐藏了
03_函数式编程
- 函数是”第一等公民“
- 纯函数 / 无副作用
- 高阶函数 / 闭包
JS可以通过配合famdajs这个库来实现函数式编程
03_函数式编程-First Class Function
03_函数式编程-Pure Function
-
优势
- 可缓存
- 可移植
- 可测试
- 可推理
- 可并行
03_函数式编程-Currying(柯里化)
柯里化:利用函数和高阶函数来解决参数传来传去的麻烦,并且可以延迟全部参数的准备工作
不去柯里化 -> 柯里化
柯里化的实现也有利用闭包和高阶函数的特性
03_函数式编程-Composition
有了组合的概念,可以对代码的一些规则进行优化重写
03_函数式编程-Functor
可以当做容器的类型,类型支持对容器内元素进行操作
常见的functor:Array(iterable).map、Promise.then
03_函数式编程-Monad
可以去除嵌套容器的容器类型
常见monad:Array.flatMap、Promise.then
03_函数式编程-Applicative
直接对两个容器进行操作
03_响应式编程
- 异步 / 离散的函数式编程
- 数据流
- 操作符
- 过滤
- 合并
- 转化
- 高阶
JS结合RxJS工具库可以来实现响应式编程
03_响应式编程-Observable
- 观察者模式
- 迭代器模式
- Promise / EventTarget超集*
03_响应式编程-操作符
响应式编程的"compose"
- 合并
- 过滤
- 转化
- 异常处理
- 多播
以下就是一个转化操作
03_响应式编程-Monad
- 去除嵌套的Obervable
03_总结
04.领域特定语言
04.什么是领域特定语言
- Domain-specific language(DSL):应用于特点领域的语言
- HTML
- SQL
↓
- General-purpose language (通用性语言)
- C / C++
- Javascript
- ...
04.语言运行
lexer: 词法解析器 => 形成短语
parser:语法解析器 => 形成语法树
visit:遍历分析
04_lexer
主要是把一些语言切分成有意义的token ,一般通过正则表达式去进行区分
SQL Token分类
- 注释
- 关键字
- 操作符
- 空格
- 字符串
- 字符串
- 变量
04_Parser-语法规则
上下文无关语法规则
**推导式:**表示非终结符到(非终结符或终结符)的关系
**终结符:**构成句子的实际内容,可以简单理解为词法分析中的token
**非终结符:**符号或变量的有限集合。它们表示在句子中不同类型的短语或子句
04_Parser-LL
**LL: **从左到右检查,从左到右构建语法树
04_Parser-LR
**LR:**从左到右检查,从右到左构建语法树