编程范式 | 青训营笔记

94 阅读4分钟

编程范式

编程语言

为什么需要编程语言

机器语言

image-20230418110349101

汇编语言

汇编语言就是将以前机器语言的命令,用一些简单的英文单词来表示,这样不仅很直观,对编程人员的要求也大大降低了。

高级语言

image-20230418110532557

C/C++

C:“中级语言”过程式语言代表
可对位,字节,地址直接操作
代码和数据分离倡导结构化编程
功能齐全:数据类型和控制逻辑多样化
可移植能力强
C with Classes
继承
权限控制
虚函数
多态

Lisp

LiSp:函数式语言代表

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

JavaScript

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

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

总结

image-20230418114500146

编程范式

什么是编程范式

程序语言特性

  • 是否允许副作用
  • 操作的执行顺序
  • 代码组织
  • 状态管理
  • 语法和词法

编程范式

命令式

  • 面向过程
  • 面向对象

声明式

  • 函数式
  • 响应式

过程式编程

  • 自顶向下

    image-20230418115333321

  • 结构化编程

image-20230418115419833

JS中的面向过程

//数据
export var car={
    meter:100,
    speed:10,
};
//算法
export function advanceCar(meter){
    while(car<meter){
        car.meter+=car.speed;
    }
}

面向过程式编程有什么缺点?

  • 数据与算法关联弱
  • 不利于修改和扩充
  • 不利于代码重用

为什么后面会出现面向对象

面向对象编程

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

封装

**关联数

class Car{
//数据
	meter:100,
    speed:10
  advance(meter){
  		while(this.meter<meter){
        this.meter+=this.speed;
   			 }
		}

    getSpec(){
        return `meter:${this.meter};speed:${this.speed};`;
    }
}

function main(){
var car=new Car();
car.advance(1000);
}

继承

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

class FlyCar extends Car{
    height=100
	fly(height){
        while(this.height<height){
            this.height+=this.speed
        }
    }
}

多态

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

class FlyCar extends Car{
    height=100
	fly(height){
        while(this.height<height){
            this.height+=this.speed
        }
    }
	getSpec(){
        return $car.getSpec()+`height:${this.height};`;
    }
}

function showCarSpec(car){
    new Model({
        content:car.getSpec(),
        
    }).show();
}

依赖注入

去除代码耦合

image-20230418130241922

image-20230418130312931

五大原则

  • 单一职责原则sRP(Single Responsibility Principle)

    一个类应该有且只有一个去改变它的理由,这意味着一个类应该只有一项工作。

  • 开放封闭原则oCP(Open-Close Principle)

    对象或实体应该对扩展开放,对修改封闭。

  • 里式替换原则LSP(the Liskov Substitution Principle LSP)

    在对象 x 为类型 T 时 q(x) 成立,那么当 S 是 T 的子类时,对象 y 为类型 S 时 q(y) 也应成立。(即对父类的调用同样适用于子类)

  • 依赖倒置原则DIP(the Dependency Inversion Principle DIP)

    高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。具体实现应该依赖于抽象,而不是抽象依赖于实现。

  • 接口分离原则lsP(the Interface Segregation Principle ISP)

    不应强迫客户端实现一个它用不上的接口,或是说客户端不应该被迫依赖它们不使用的方法,使用多个专门的接口比使用单个接口要好的多!

问题

面向对象编程有什么缺点?

面向对象编程语言的问题在于,它总是附带着所有
它需要的隐含环境。你想要一个香蕉,但得到的却
是一个大猩猩拿着香蕉,而且还有整个丛林。
						Joe Armstrong(Erlang创始人)

为什么我们推荐函数式编程

函数式编程

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

First Class Function

image-20230418130958148

Pure Function

优势

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

image-20230418131049829

Currying

image-20230418203647481

image-20230418203704117

image-20230418203713255

Composition

image-20230418203749783

image-20230418203820204

image-20230418203838691

associativity:compose(f,compose(g,h))===compose(compose(f,g).h)
map's composition law:compose(map(f),map(g))===map(compose(f,g));

Functor

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

常见的functor:Array(Iterable).map,Promise.then

image-20230418204050873

Monad

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

常见monad:Array.flatMap Promise.then

image-20230418204140111

image-20230418204222561

Applicative

直接对两个容器直接操作

image-20230418204317979

image-20230418204358001

Identity:Maybe(id).ap(v)===v:
Homomorphism:Maybe(f).ap(Maybe(x))===Maybe(f(x));
Interchange:v.ap(Maybe(x))===Maybe(f =f(x)).ap(v);
Composition:Maybe(compose).ap(u).ap(v).ap(w)===u.ap(v.ap(w));

响应式编程

异步/离散的函数式编程

  • 数据流
  • 操作符
    • 过滤

    • 合并

    • 转化

    • 高阶

Observable

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

image-20230418204705593

image-20230418204719274

操作符

响应式编程的“compose”

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

image-20230418204812522

Monad

去除嵌套的Observable

image-20230418204942924

image-20230418204951531

总结

image-20230418205114146

领域特定

image-20230418205238916

语言运行

image-20230418205357995

lexer

  • SQL Token分类
  • 注释
  • 关键字
  • 操作符
  • 空格
  • 字符串
  • 变量

Parser语法规则

上下文无关语法规则

image-20230418205627105

推导式:表示非终结符到(非终结符或终结符)的关系。 终结符:构成句子的实际内容。可以简单理解为词法分析中的token。 非终结符:符号或变量的有限集合。它们表示在句子中不同类型的短语或子句。

Parser LL

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

image-20230418212532355

Parser LR

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

image-20230418212751997

LL(K)>LR(1)>LL(1)

tools

exp ::exp'+'exp
exp	::=exp '*' exp
exp ::='NUMBER'
npx kison -m llk -g grammar.js -o cal.js

visitor

image-20230418213040997

总结

image-20230418213107512