函数式编程

124 阅读1分钟
1. 函数柯里化
function curry(func) {
  return function curriedFn(...args) {
    if (args.length < func.length) {
      return function () {
        return curriedFn(...args.concat(Array.from(arguments)));
      };
    }
    return func(...args);
  };
}
2. 函数组合
function compose(...args) {
  return function (value) {
    return args.reverse().reduce(function (acc, fn) {
      return fn(acc);
    }, value);
  };
}

3. 函子

  1. 容器:包含值和值的变形关系(这个变形关系就是函数)
  2. 函子:是一个特殊的容器,通过一个普通的对象来实现,该对象具有map方法,map方法可以进行一个蜀汉对值进行处理。
class Container {
  static of (value) {
    return new Container(value)
  }

  constructor (value) {
    this._value = value
  }

  map (fn) {
    return Container.of(fn(this._value))
  }
}

let r = Container.of(5)
          .map(x => x + 2)
          .map(x => x * x)

总结:

  1. 函数式编程的运算不直接操作值,而是由函子来完成。
  2. 函子就是一个实现map的契约的对象
  3. 我们可以把函子想象成一个盒子,这个盒子装了一个值,想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
  4. 最终map方法返回一个包含新值的盒子(函子)

4. MayBe函子

解决空值问题

class MayBe {
  static of(value) {
    return new MayBe(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    return this.isNothing() ? MayBe.of(null) : this.map(fn(this._value));
  }
  isNothing() {
    return this._value === null || this._value === undefined;
  }
}

5. Either函子

Either 函子

  1. Either两者中的任何一个。类似if ...else... 的处理
  2. 异常会让函数变得不纯,Either可以用来处理异常
class Left {
  static of(value) {
    return new Left(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    return this;
  }
}

class Right {
  static of(value) {
    return new Right(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    return Right.of(fn(this._value));
  }
}

const r1 = Right.of(12).map((x) => x + 2); //{ _value: 14 }
const l1 = Left.of(12).map((x) => x + 2); //{ _value: 12 }

function parseJSON(str) {
  try {
    return Right.of(JSON.parse(str));
  } catch (err) {
    return Left.of({ error: err.message });
  }
}

const p = parseJSON("{name:kebe}"); 
//{ _value: { error: 'Unexpected token n in JSON at position 1' } }
const p1 = parseJSON('{"name":"kebe"}');
//{ _value: { name: 'kebe' } }
const p2 = parseJSON('{"name":"kebe"}').map((x) => x.toUpperCase());