网资酷

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 103|回复: 2

函数式编程——云隐

[复制链接]

2

主题

7

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2022-12-2 12:53:11 | 显示全部楼层 |阅读模式
一、函数式编程的出现


  • 发展历程:

  • 命令(脚本)式编程 -> 以一行代码为单元,逐步运行
  • 面向对象编程 -> 以对象为操作单位
  • 函数式编程 -> 函数为王
1. 问题的出现 - 从一道面试题说起

    // 面试题: 上接浏览器原理 —— 参数parse

    // 1. url中参数是如何展示数组的
    // location.search => '?name[]=progressive$%coding&name[]=objective$%coding&name[]=functional$%coding'
    // 2. 参数提取拼接数组
    // ['progressive$%coding', 'objective$%coding', 'functional$%coding']
    // 3. 转换成数组对象做存储
    // [{name: 'Progressive Coding'}, {name: 'Objective Coding'}, {name: 'Functional Coding'}]

    // 解:
    // 1. 字符串拆分数组 遍历
    // 2. 字符串=>key value 遍历

    const _array = ['progressive$%coding', 'objective$%coding', 'functional$%coding'];
    const _objArr = [];

    const nameParser = (array, objArr) => {
        // 对于数组的处理部分
        array.forEach(item => {
            let names = item.split('$%');
            let newName = [];

            // 对于name的处理部分
            names.forEach(name => {
                let nameItem = name[0].toUpperCase() + name[1].slice(1);

                newName.push(nameItem);
            })
            objArr.push({
                name: newName.join(' ');
            })
        })
        return objArr;
    }

    // 问题:
    // 1. 过程中存在逻辑包裹 - 看完整段才明白在做啥
    // 2. 存在临时变量,首尾封闭 - 迭代拓展难度较高
解决方案

    // step1. 需求分析 => 数组 > 数组对象 => [字符串 > 对象]
    // nameParser => [objHelper :: string > object]

    // step2. 功能明确 => objHelper = formatName + assembleObj

    // step3. 功能拆分 => objHelper = [(split + capitalize + join)] + assembleObj

    // step4. 代码实现
    const _array = ['progressive$%coding', 'objective$%coding', 'functional$%coding'];

    // 原子操作
    const assembleObj = (key, x) => {
        let obj = {};

        obj[key] = x;
        return obj;
    }

    const capitalize = str => str[0].toUpperCase() + str.slice(1);

    // 声明结构 - ramda
    const formatName = R.merge(join(' '), map(capitalize), split('$%'));
    const objHelper = R.merge(assembleObj('name'), formatName);
    const nameParser = map(objHelper);

    nameParser(_array);

    // 面试题:正确的使用遍历 - for forEach map filter sort……
    // 本质作用 => 通用遍历 | 遍历逻辑处理 | 生成数组 - 处理 | 生成数组 - 过滤 | sort - 排序……
二、函数式编程原理特点

1. 什么是函数式的原理


  • 加法结合律 | 因式分解 | 完全平方公式 => 原子组合的变化 a + b + c = (a + b) + c
  • 水源 => 组合(水管 + 弯头) =>花洒
2. 理论思想

a. 一等公民 —— 函数 => 1. 逻辑功能的落脚点 —— 函数 2. 实现函数 + 拼接流程

b. 声明式编程 => 声明需求 - 更贴近语言习惯 react vue3

c. 惰性执行 - 无缝衔接,性能节约

// 惰性函数
const program = name => {
    if (name === 'progressive') {
        return program = () => {
            console.log('this is progressive');
        }
    } else if(name === 'objective') {
        return program = () => {
            console.log('this is objective');
        }
    } else {
        return program = () => {
            console.log('this is functional');
        }
    }
}

program('progressive')();
program();
3. 无状态与无副作用


  • a. 无状态 - 幂等;数据不可变 - 不可操作改变源数据
  • b. 无副作用 - 函数内部不可直接对系统中任何参数变量做直接改动
三、实际开发

1. 纯函数的改造

    const _class = {
        name: 'objective'
    }

    // 函数内部引入了外部变量 —— 无状态
    const score = str => _class.name + ':' + str;

    // 修改了传入参数 —— 无副作用
    const changeClass = (obj, name) => obj.name = name;

    changeClass(_class, 'functional');
    score('good');

    // #####################
    import _ from 'lodash';

    const _class = {
        name: 'objective'
    }

    const score = (obj, str) => _.deepClone(obj).name + ':' + str;
    const changeClass = (obj, name) => ({ ...obj, name });

    changeClass(_class, 'functional');
    score(_class, 'good');
2. 流水线的组装 - 加工 & 组装

a. 加工 - 科里化

    // f(x, y, z) -> f(x)(y)(z)
    const sum = (x, y) => {
        return x + y;
    }
    sum(1, 1);

    const add = x => {
        return y => {
            return x + y;
        }
    }
    add(1)(1);

    // 要实现 体系 = 加工 + 组装,单个加工的输入输出应该单值化 -> 单元函数
    const fetch = ajax(method, url, params);

    const fetch = ajax.get(url);
    const request = fetch(params);

    const fetch = ajax(method)(url)(params);

    组合(request, fetch)

  • 面试题:手写构造可拆分传参的累加函数 add(1)(2)(3)(4)
    // 1. 构造科里化的结构
    // 2. 输入 处理外层arguments => 类数组处理
    // 3. 传入参数无线拓展 => 内层递归 => 返回递归函数本身
    // 4. 主功能区
    // 5. 输出 从函数到产出 toString的替换

    const add = function() {
        // input
        let args = Array.prototype.slice.call(arguments);

        // 内层函数
        let inner = function() {
            args.push(...arguments);

            return inner;
        }

        // 主功能区
        inner.toString = function() {
            return args.reduce((prev, cur) => {
                return prev + cur;
            })
        }

        return inner;
    }

    '' + add(1)(2)(3)(4)  // 10

    // 如何去调原来的toString => 用.call
b. 流水线 - 组装函数

    const compose = (f, g) => x => f(g(x));

    const sum1 = x => x + 1;
    const sum2 = x => x + 2;
    const sum12 = compose(sum2, sum1);
    sum12(1);

  • 实际实现使用
    // 命令式
    trim(reverse(toUpperCase(map(arr))))
    // 面向对象
    arr.map().toUpperCase().reverse().trim()

    // 函数式
    const result = compose(trim, reverse, toUpperCase, map)

    pipe() // history | grep rm
四、函子

    // 一封情书
    class Mail {
        constructor(content) {
            this.content = content;
        }
        map(fn) {
            return new Mail(fn(this.content));
        }
    }

    // 1. 写情书
    let mail1 = new Mail('love');

    // 2. 读了信
    let mail2 = mail1.map(function(mail) {
        return read(mail);
    });

    // 3. 涂抹了
    let mail3 = mail2.map(function(mail) {
        return cross(mail);
    });

    // 4. 别人查看的时候
    mail3.map(function(mail) {
        return read(mail);
    })

    // 链式
    new Mail('love').map(read).map(burn).map(read);

    // Functor(函子)遵守了一些特定规则的容器或者数据协议
    // 具有一个通用的map方法,返回新实例
    // 具有结合外部的运算能力 => 可在管道中处理不同层级又很纯净的单元操作
回复

使用道具 举报

1

主题

6

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2025-5-11 22:03:53 | 显示全部楼层
这么强,支持楼主,佩服
回复

使用道具 举报

0

主题

6

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2025-6-24 01:09:05 | 显示全部楼层
楼主呀,,,您太有才了。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|网资酷

GMT+8, 2025-7-5 22:25 , Processed in 0.080831 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表