Programming Paradigms: Functional

 20th August 2020 at 2:19pm

使用 JS 演示一些函数式编程的方法。

pipe

如何使用管道,使一个参数被多个函数依次处理后输出。例子来自 Code with Mosh 的 Redux 课程

import { pipe } from "lodash/fp";

const pickTag = obj => obj.tag;
const toLowerCase = str => str.toLowerCase();
const bracketify = str => `(${str})`;

const transform = pipe(pickTag, toLowerCase, bracketify);

// output: "(javascript)"
const output = transform({ tag: "JAVASCRIPT" });

Currying

Currying 是一种代码组织方式,用于将一个接受多参数的函数,变成只接受一个参数。通过一个返回函数的函数来实现。函数式编程中一般只接受一个参数。

// Function which takes two argument
function add(a, b) {
  return a + b;
}

// Currying: transform into function which takes one argument
function add(a) {
  return function(b) {
    return a + b;
  };
}

const add2 = a => b => a + b; // (a, b) => a + b

add(1)(5); // add(1, 5)
// N => 1

Python 的 functools.partial 也可以用来实现类似的效果。

Tranform immutable data

对于不可变数据结构,如何新增、更新或者删除字段。例子来自 Code with Mosh 的 Redux 课程JavaScript: Immutable Object 有更多讨论。

变化数组:

const numbers = [1, 2, 3];

// Adding
const index = numbers.indexOf(2);
const added = [...numbers.slice(0, index), 4, ...numbers.slice(index)];

// Removing
const removed = numbers.filter(n => n !== 2);

// Updating
const updated = numbers.map(n => (n === 2 ? 20 : n));
console.log(updated);

变化对象:

const person = {
  name: "John",
  address: {
    country: "USA",
    city: "San Francisco"
  }
};
const updated = {
  ...person,
  address: {
    ...person.address,
    city: "New York"
  },
  name: "Bob"
};
console.log(person);

注意,采用 spread operation 时,spread 的语句要写在前面。写在后面的字段有更高的优先级。