编程范式|青训营笔记

169 阅读3分钟

1.编程语言

发展历史:机器语言->汇编语言->高级语言

经典高级语言:

  • C:面向过程代表。对位,字节,地址直接进行操作。结构化。可以移植性强
  • C++:面向对象代表
  • List:函数式语言的代表。无法操作指针,地址。列表即数据。闭包
  • JavaScript:多范式代表。基于原型和头函数的多范式语言。过程式。面向对象。函数式。响应式

2.编程范式

1.程序语言的特性

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

2.编程范式

  • 命令式

    侧重于如何操作机器改变状态

    • 面向过程:根据整体流程

    • 面向对象:根据操作和状态

  • 声明式

    侧重于声明想要的结果,不指明具体的操作

    • 函数式:函数
    • 响应式:数据流和映射函数

3.过程式编程

1.特点

  • 自顶向下

  • 结构化编程

    • 顺序结构
    • 选择结构
    • 循环结构

2.JS中的面向过程

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

3.缺点

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

4.面向对象

1.特点

  • 封装

    class Car{
    	meter = 100  //数据
    	speed 100
    	advance(meter){    //算法
    		while(this.meter<meter){
    			this.meter += this.speed;
    		}
    	}
    }
    
    
  • 继承

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

  • 多态

    一个类的函数在不同的情况下有不同的表现形式,可以进行接口共享,达到函数复用

  • 依赖注入

    去除代码的耦合性

    //耦特定实现
    class Car{
    	engine = new Engine()
    	wheel = new Wheel()   
        
        run(){
            this.engine.star();
            this.wheel.run();
        }
    }
    
    function main(){
        var car = new Car();
        
        car.run();
    }
    

    使用依赖注入后:

    class Car{
        @inject('engine')    //声明依赖
        engine;
        
        @inject('wheel')
        wheel;
        
        run(){
            this.engine.star();
            this.wheel.run();
        }
    }
    
    function main(){
        var container = new Container();       //声明实现
        container.bind('engine',Engine);        
        container.bind('car',Car);              
        container.bind('wheel',Wheel);
        
        var car = container.getObject('car');  //依赖注入
        car.run();                               
    }
    

2.原则

  • 单一职责原则SRP:类的功能单一
  • 开放封闭原则OCP:扩展方面是开放的,更改方面是封闭的
  • 里式替换原则LSP:子类可以替换父类,出现在父类的任何地方
  • 依赖导致原则DIP:具体依赖抽象,上层依赖下层。要使用其他的类,就给这个类定义一个接口
  • 接口分离原则ISP:依赖要通过接口进行处理,不能依赖于具体类的实现

3.缺点

数据修改完全被隐藏,补充代码繁琐

5.函数式编程

  • First Class Function函数是第一等公民

    函数和其他数据类型具备同等的地位,可以赋值个某个变量,也可以作为函数的参数,返回值

  • Prue Function纯函数/无副作用

    相同的输入,总会得到相同的输出,在执行过程中没有任何的副作用

    纯函数:不依赖于外部环境

    无副作用:产生外部可观察的变化,比如对外界的数据进行修改

  • Carrying柯里化

    利用函数与高阶函数,将接受多个参数的函数编程接受一个参数的函数,并返回余下的参数而且返回结果的新函数

  • Composition组合式

    如果一个函数需要铜鼓哦多个函数处理才能得到最终结果,可以把中间过程的函数合并成一个函数

    函数组合默认式从右向左执行,满足结合律

    //手动组合
    const toUpperCase = x => x.toUpperCase();
    const log = x => console.log;44function alertUppercase(str){
        log(toUpperCase(x));
    }
    
    //自动组合
    const alertUppercaseFn = compose(log,toUpperCase);
    
  • Functor仿子

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

    常见Functor:Arry.map,Promise.then

    可以将特殊情况都封装到容器中

    a.b=null?(a.b.c!=null?(a.b.c.d!=null?a.b.c.d.e:null):null)
    //可以改写成
    new Maybe(a).map(prop('b')).map(prop('c')).map(prop('d')).map(prop('e'));
    
    class Maybe{
        constructor(x){
            this.$value = x;
        }
        
        map(fn){
            return this.$value == null?this:new Maybe(fn(this.$value));
        }
    }
    
  • Monad

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

    常见Monad:Array.flatMap,Promise.then

  • Applicative

    对两个容器直接操作

6.响应式编程

异步/离散的函数式编程

  • 数据流
  • 操作符
    • 过滤
    • 合并
    • 转化
    • 高阶

1.Observable

  • 观察者模式
  • 迭代器模式

observable

2.操作符

响应式编程的“compose”

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

3.Monad

去除嵌套的Observable

7.领域特定语言

领域特定语言(例如:HTML,SQL)一般都是由通用语言(例如:C,C++)实现的

语言的运行:

  1. 词法解析器处理形成短语
  2. 语法解析器处理形成语法树
  3. 遍历分析
  4. 代码生成

语言运行

1.lexer

将语言切分成token,通常使用正则表达式

lexer

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

2.Parser

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

终结符:构成句子的实际内容

非终结符:符号或变量的有限集合,表现在句子中不同类型的短语或子句

3.tools

帮助构建语法树

npx kison -m llk -g grammar.js -o cal.js

4.visitor

visitor