当前位置: 首页 > article >正文

函数式编程范式(二)

函数式编程范式二纯函数什么是纯函数函数式编程中的函数就是纯函数。具体特征就是相同的输入永远会得到相同的输出而且没有任何可观察的副作用。纯函数就类似于数学中函数用来描述输入与输出之间的关系y f(x)下面举一个 纯函数 和 非纯函数 的例子Array.prototype.slice和Array.prototype.spliceletarr[1,2,3,4,5,6,7,8]// 纯函数console.log(arr.slice(0,2))// [ 1, 2 ]console.log(arr.slice(0,2))// [ 1, 2 ]console.log(arr.slice(0,2))// [ 1, 2 ]// 非纯函数console.log(arr.splice(0,2))// [ 1, 2 ]console.log(arr.splice(0,2))// [ 3, 4 ]console.log(arr.splice(0,2))// [ 5, 6 ]函数式编程不会保留中间的结果所以变量是不可变的无状态的。我们可以将一个函数的执行结果交给另外一个函数去处理。纯函数的好处可预测性纯函数的「相同输入→相同输出」特性让代码行为完全可预测 —— 这是纯函数最核心的价值。可缓存性Memoization提升性能因为纯函数的输出只依赖输入所以可以把「输入→输出」的映射缓存起来重复调用时直接返回缓存结果避免重复计算。可测试性纯函数无需依赖外部环境测试时只需关注 “输入→输出”不用模拟 / 搭建复杂的测试环境。可并行执行纯函数不依赖外部状态也不修改外部状态因此可以安全地在多线程 / 并发环境中执行比如 Web Worker、Node.js 多进程无需担心 “竞态条件”多个线程同时修改同一变量。无副作用避免隐藏 bug纯函数不会修改外部状态因此不会引发 “意外的变量修改”“状态污染” 等隐蔽 bug。副作用我们再纯函数的优点中提到了副作用那究竟什么是副作用呢副作用是函数 “本职工作计算返回值” 之外的 “额外操作”这些操作会影响函数外部的状态或环境导致函数的行为不可预测、依赖外部上下文不纯。常见的副作用来源函数修改了自身作用域之外的变量全局变量、闭包变量、函数参数中的引用类型依赖随机值 / 时间等不可控因素修改函数参数的原始值尤其引用类型操作 DOM修改页面元素、绑定事件发起网络请求读写文件操作本地存储实际开发中我们不可能完全避免副作用比如前端必须操作 DOM、必须发网络请求我们只能尽可能的让副作用 “可控、可追踪”。柯里化柯里化是将一个接收多个参数的函数转换成一系列只接收单个参数的函数的过程。最终通过依次调用这些单参数函数逐步收集参数直到所有参数收集完毕后执行原逻辑并返回结果。有点抽象我们用一个例子来演示一下// 普通函数一次接收3个参数constadd(a:number,b:number,c:number){returnabc}add(1,2,3)// 直接传所有参数返回6// 柯里化函数分步接收参数constcurryAdd(a:number)// 接收第一个参数a返回接收第二个参数的函数(b:number)// 接收第二个参数b返回接收第三个参数的函数(c:number)// 接收最后一个参数c执行原逻辑abc// 调用方式1分步传参核心特征curryAdd(1)(2)(3)// 依次传参返回6// 调用方式2也可以部分传参偏应用constadd1curryAdd(1)// 固定第一个参数为1constadd1And2add1(2)// 固定第二个参数为2add1And2(3)// 传第三个参数返回6add1And2(4)// 复用传新的第三个参数返回7柯里化的核心用途参数复用最常用可以固定函数的部分参数生成一个新函数后续复用这个新函数时无需重复传固定参数。延迟执行控制执行时机柯里化函数不会立即执行原逻辑而是等参数收集完毕后才执行适合需要 “先收集参数、后执行” 的场景如事件处理、防抖节流。函数粒度细化符合 “单一职责”把多参数函数拆分成多个单参数函数每个函数只负责处理一个参数逻辑更清晰也更容易组合函数组合是函数式编程的核心。柯里化通用函数上面的柯里化示例中可以看出来我们是利用了高阶函数和闭包的特性手动嵌套函数实现了函数的柯里化但是这种方法并不通用。lodash中有提供一个通用的柯里化函数import{curry}fromlodash-es// 普通函数一次接收3个参数constadd(a:number,b:number,c:number){returnabc}constcurryAddcurry(add)curryAdd(1)(2)(3)// 6constadd1curryAdd(1)constadd1And2add1(2)add1And2(3)// 6add1And2(4)// 7// 还可以这样调用curryAdd(1,2,3)curryAdd(1,2)(3)curryAdd(1)(2,3)为了便于更好的理解柯里化我们手动模拟一下_.curry(func)的实现constcurryTextends(...arg:any[])any(func:T){returnfunctioncurriedFn(...args:any[]){// 判断实参和形参的个数if(args.lengthfunc.length){// 只传部分参数返回传递剩余参数的函数returnfunction(...nextArgs:any[]){// 拼接后续传递参数直至实参个数大于等于行程returncurriedFn(...args.concat(nextArgs))}}// 直接传递全量的参数returnfunc(...args)}}函数组合函数组合Function Composition是函数式编程中的核心概念它的本质是将多个单功能的函数组合成一个新函数让数据依次通过这些函数处理最终得到结果。我们如果利用纯函数和柯里化很容易写出洋葱代码f(g(h(x)))例如// 转大写consttoUpperCase(str:string)str.toUpperCase();// 去除空格consttrim(str:string)str.trim();// 加感叹号constaddExclamation(str:string)${str}!;constresulttoUpperCase(trim(addExclamation( hello world )));// 缺点阅读顺序是从内到外不直观我们只要保证这些过程是纯函数那么就可以利用函数组合将这个复杂的过程组合成一个函数这样我们就只需要调用这个组合函数就可以实现功能不用关心中间函数的输入输出。constprocessStrcompose(addExclamation,trim,toUpperCase);constresultprocessStr( hello world );// HELLO WORLD!!通用组合函数// flow 从左往右执行 flowRight从右往左执行import{flow,flowRight}fromlodash-es// 转大写consttoUpperCase(str:string)str.toUpperCase();// 去除空格consttrim(str:string)str.trim();// 加感叹号constaddExclamation(str:string)${str}!;constfnflow(toUpperCase,trim,addExclamation)console.log(fn( hello world ))exportdefault{}模拟实现 compose/** * 函数组合从右到左执行 * param funcs 要组合的函数数组 * returns 组合后的新函数 */constcompose(...funcs:any[]){return(value:any){returnfuncs.reverse().reduce((acc,fn)fn(acc),value)}}函数组合默认是从右到左compose而管道函数pipe是从左到右更符合日常阅读习惯pipe(管道函数)去掉reverse()即可。结合律associativity函数的组合要满足结合律单独组合某些函数结果都是一样的import{flowRight,toUpper,first,reverse}fromlodash-es// 取得数组最后一项并转为大写// 下面三种写法 结果一样constfn1flowRight(toUpper,first,reverse)constfn2flowRight(toUpper,flowRight(first,reverse))constfn3flowRight(flowRight(toUpper,first),reverse)console.log(fn1([one,two,three]))// THREEconsole.log(fn2([one,two,three]))// THREEconsole.log(fn3([one,two,three]))// THREE调试组合函数我们可以通过插入调试函数的方式来打印调试上一步执行的结果。import{flowRight,toUpper,first,reverse}fromlodash-esconstlog(value:string){console.log(value)returnvalue}// 取得数组最后一项并转为大写constfnflowRight(toUpper,first,log,reverse)fn1([one,two,three])// [ three, two, one ]我们也可以改造一下log函数增加一个tag参数方便查看。consttracecurry((tag:string,value:any){console.log(tag: value)returnvalue})constfn1flowRight(toUpper,first,trace(after reverse),reverse)Point FreePoint Free也译作 “无值风格” 或 “无参风格”是函数式编程中的一种编码范式核心思想是定义函数时不直接提及函数所操作的参数即 “点”而是通过组合已有的函数来实现逻辑。简单来说普通写法会显式写出参数而 Point Free 写法完全隐藏参数让代码更简洁、更专注于 “做什么” 而非 “对谁做”。非 Point Free 模式// 显式声明参数 str这就是“点”constprocessStr(str)str.trim().toUpperCase();// 调用console.log(processStr( hello world ));// 输出HELLO WORLDPoint Free 模式// 先定义基础函数consttrim(str)str.trim();consttoUpper(str)str.toUpperCase();// 组合函数完全不提及参数constprocessStr(str)toUpper(trim(str));// 更极致的 Point Free借助函数组合工具constcompose(f,g)(x)f(g(x));// 简单的组合函数constprocessStrPointFreecompose(toUpper,trim);// 调用结果和普通写法一致console.log(processStrPointFree( hello world ));// 输出HELLO WORLD为什么要用 Point Free代码更简洁去掉冗余的参数声明聚焦核心逻辑复用性更高通过组合已有函数实现新功能避免重复写逻辑可读性更好函数名直接体现逻辑意图比如compose(toUpper, trim)一眼就能看出 “先去空格再转大写”易于测试组合的基础函数可单独测试减少整体逻辑的测试复杂度。

相关文章:

函数式编程范式(二)

函数式编程范式(二) 纯函数 什么是纯函数? 函数式编程中的函数就是纯函数。 具体特征就是,相同的输入永远会得到相同的输出,而且没有任何可观察的副作用。 纯函数就类似于数学中函数(用来描述输入与输出之间…...

Facebook游戏开发必备:用Graph API获取用户数据与好友列表的实战技巧

Facebook游戏开发进阶:Graph API数据获取与权限管理实战解析 在社交游戏开发中,Facebook平台的数据接入能力直接决定了用户体验的丰富程度。许多开发者虽然完成了基础SDK集成,却在处理用户画像构建、社交关系链同步等进阶功能时频频受阻。本文…...

代码随想录算法训练营第四十八天| 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

300. 最长递增子序列 思路:首先注意这里的递增不一定要连续,可以是隔了几个数字的递增。那么这道题设dp数组的含义比较有意思:dp[i]表示i之前包括i的以nums[i]结尾的最长递增子序列的长度。当nums[i]大于nums[j]的时候,我们可以写…...

UE5实战:Alembic文件导入全攻略(含Maya导出避坑技巧)

UE5实战:Alembic文件导入全流程解析与性能优化指南 在影视级实时动画制作流程中,Alembic文件格式已成为跨软件协作的黄金标准。作为开源的几何体缓存交换格式,它能够将Maya中复杂的动态模拟完美迁移到UE5的实时渲染环境中。本文将深入解析从M…...

多场耦合优化-主题034-形状优化与尺寸优化

主题034:形状优化与尺寸优化 1. 引言 结构优化是现代工程设计中的核心技术,旨在通过系统化的方法寻找最优的结构形式,以满足特定的性能要求。结构优化通常分为三个层次:尺寸优化(Sizing Optimization)、形状…...

PLC设计毕业设计入门指南:从硬件选型到梯形图实战

作为一名自动化专业的过来人,我深知做PLC毕业设计时那种既兴奋又迷茫的感觉。面对一堆陌生的硬件型号和复杂的编程软件,很多同学第一步就卡住了——该选哪个牌子的PLC?I/O点怎么算?梯形图画出来总是不对劲,仿真通过了&…...

Sigil:开源EPUB编辑工具解决电子书制作核心痛点的全面方案

Sigil:开源EPUB编辑工具解决电子书制作核心痛点的全面方案 【免费下载链接】Sigil Sigil is a multi-platform EPUB ebook editor 项目地址: https://gitcode.com/gh_mirrors/si/Sigil 在数字化阅读日益普及的今天,电子书制作面临着格式标准化、编…...

如何解决Sublime Text乱码问题:编码转换工具完全指南

如何解决Sublime Text乱码问题:编码转换工具完全指南 【免费下载链接】ConvertToUTF8 A Sublime Text 2 & 3 plugin for editing and saving files encoded in GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS, etc. 项目地址: https://gitcode.com/gh_mirrors/co/Conv…...

那些被Windows“藏起来”的功能:找回属于你的选择权

引言:你的电脑,谁说了算?你有没有发现,Windows这些年越来越“霸道”了?明明习惯任务栏在左侧,新系统却强行把它固定在底部中央;明明喜欢经典右键菜单,新版本非要折叠起来多按一次“显…...

3大突破如何重塑Web机器学习开发?Transformers.js移动端AI框架深度解析

3大突破如何重塑Web机器学习开发?Transformers.js移动端AI框架深度解析 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: htt…...

从“不会写代码”到亲手上线产品:Makund 与 Madav 眼中的 AI 软件新范式

从“不会写代码”到亲手上线产品:Makund 与 Madav 眼中的 AI 软件新范式 开头摘要 在这场访谈中,Makund 与 Madav 围绕 Emergent 的产品演进、技术路线和用户变化,分享了他们对“非技术用户如何借助 AI 构建生产级软件”的判断。两人认为&…...

告别乱码困扰:ConvertToUTF8的高效编码转换完全指南

告别乱码困扰:ConvertToUTF8的高效编码转换完全指南 【免费下载链接】ConvertToUTF8 A Sublime Text 2 & 3 plugin for editing and saving files encoded in GBK, BIG5, EUC-KR, EUC-JP, Shift_JIS, etc. 项目地址: https://gitcode.com/gh_mirrors/co/Conve…...

生成PPT网站推荐|AI博主实测,程序员/职场人告别熬夜排版

一、PPT创作核心痛点分析(精准戳中CSDN用户需求)结合自身使用体验和身边程序员、职场人的反馈,目前大家在PPT创作中主要面临四大核心痛点,也是我们选择PPT生成网站的核心考量方向:1. 排版效率低:手动调整版…...

告别黑苹果配置噩梦:OpCore Simplify如何让EFI构建像搭积木一样简单

告别黑苹果配置噩梦:OpCore Simplify如何让EFI构建像搭积木一样简单 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 当你第三次因为ACPI补…...

如何借助AI驱动工具提升化学研究效率?面向科研人员的智能解决方案

如何借助AI驱动工具提升化学研究效率?面向科研人员的智能解决方案 【免费下载链接】chemcrow-public Chemcrow 项目地址: https://gitcode.com/gh_mirrors/ch/chemcrow-public ChemCrow是一款基于人工智能技术的化学任务处理工具,通过整合Langcha…...

如何通过Zotero PDF2zh插件解决英文文献阅读效率问题

如何通过Zotero PDF2zh插件解决英文文献阅读效率问题 【免费下载链接】zotero-pdf2zh PDF2zh for Zotero | Zotero PDF中文翻译插件 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-pdf2zh 在学术研究与文献管理过程中,英文文献的高效处理始终是研究者…...

信贷风控必看:WOE分箱从原理到落地(含Python实现与业务解释)

信贷风控中的WOE分箱:原理、实践与业务价值解析 在金融风控领域,数据科学家们常常需要将连续变量转化为离散区间,这个过程被称为"分箱"或"分桶"。而WOE(Weight of Evidence)分箱则是信用评分卡开发…...

StarWind iSCSI服务器避坑实录:从安装包获取到ESXi权限配置的全流程

StarWind iSCSI服务器实战指南:避开那些年我们踩过的坑 在虚拟化技术领域,iSCSI存储解决方案因其成本效益和灵活性备受青睐。StarWind作为一款高性能的iSCSI目标服务器软件,能够将普通服务器转变为专业级存储设备。然而,从软件获取…...

基于SSM的新闻稿件管理系统的设计实现 报社稿件记者管理系统

目录系统需求分析技术选型数据库设计核心功能实现统计与检索测试与部署扩展性考虑项目技术支持可定制开发之功能创新亮点源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作系统需求分析 明确系统核心功能需求:用户角色分为管理员、…...

在 WorkBuddy 中添加自定义Ollama模型方法,已成功测试

概述 本文档总结了如何通过 WorkBuddy 的 international-ai-deploy 技能来添加和管理自定义 AI 模型,特别是针对本地 Ollama 服务的配置。文档涵盖了完整的流程,从技能安装到模型配置文件的创建。 安装 international-ai-deploy 技能 方法1:通…...

【数据库】Navicat16 安装与破解全攻略:从下载到无限试用

1. Navicat16 简介与下载准备 Navicat 是一款广受欢迎的数据库管理工具,支持 MySQL、PostgreSQL、Oracle、SQL Server 等多种数据库。Navicat16 是最新版本,相比之前版本在性能和功能上都有显著提升。对于数据库管理员和开发者来说,Navicat …...

VMware虚拟机下Linux非LVM分区扩容实战:从删除快照到xfs_growfs完整流程

VMware虚拟机下Linux非LVM分区扩容实战指南 在虚拟化环境中,Linux系统的存储空间管理是运维人员经常需要面对的问题。特别是对于那些没有采用LVM(逻辑卷管理)的传统分区方式,当存储空间不足时,扩容操作需要格外谨慎。本…...

Nano-Banana在MATLAB中的调用方法

Nano-Banana在MATLAB中的调用方法 用最简单的方式,让MATLAB用户也能玩转Nano-Banana模型 1. 开篇:为什么要在MATLAB里调用AI模型? 如果你经常用MATLAB做科学计算或数据处理,可能会遇到这样的情况:需要一些AI能力来增强…...

从零开始掌握SIL验算实战——基于HAZOPkit的完整流程解析

1. 什么是SIL验算?为什么需要HAZOPkit? 第一次接触SIL验算的朋友可能会被这个专业术语吓到。其实简单来说,SIL(安全完整性等级)验算就像给工厂的安全系统做"体检报告"。想象一下,工厂里那些负责紧…...

Rust Axum项目实战:用sea-orm搞定数据库连接(附完整代码)

Rust Axum与Sea-ORM实战:从零构建高并发数据库服务 在当今高并发的互联网服务架构中,Rust语言因其卓越的性能和内存安全性正获得越来越多开发者的青睐。而Axum作为Rust生态中快速崛起的Web框架,与Sea-ORM这一异步ORM强强联合,为构…...

从原理到实践:图解LACP动态聚合如何提升服务器网络带宽(含内核4.1+哈希算法更新)

从原理到实践:图解LACP动态聚合如何提升服务器网络带宽(含内核4.1哈希算法更新) 在数据中心和服务器集群中,网络带宽常常成为性能瓶颈。当单条物理链路无法满足流量需求时,LACP(Link Aggregation Control P…...

Ubuntu20.04 Autoware.universe部署实战:从环境配置到避坑指南

1. 环境准备:从零开始的Ubuntu20.04配置 在开始Autoware.universe部署之前,确保你的Ubuntu20.04系统处于一个相对干净的状态非常重要。我遇到过太多因为系统环境混乱导致的问题,比如ROS版本冲突、依赖项缺失等。如果你和我一样,之…...

LightRAG | 基于 PostgreSQL 向量插件构建知识图谱增强检索

1. 为什么需要知识图谱增强的检索系统 传统向量检索虽然能快速找到语义相似的文本片段,但在处理复杂逻辑关系时往往力不从心。想象你在分析一部小说时,不仅需要找到描写"爱情"的段落,还需要理清"角色A如何通过事件X影响角色B&…...

开源工具本地化指南:Obsidian-i18n实现跨语言界面适配全流程

开源工具本地化指南:Obsidian-i18n实现跨语言界面适配全流程 【免费下载链接】obsidian-i18n 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-i18n 技术民主化的核心在于消除使用障碍,而语言壁垒往往是开源工具普及的首要瓶颈。Obsidian…...

腐烂国度1 MOD安装全攻略:从GenericModEnabler配置到实战避坑(附文件结构详解)

腐烂国度1 MOD安装全攻略:从GenericModEnabler配置到实战避坑(附文件结构详解) 第一次接触《腐烂国度1》的MOD世界时,那种既兴奋又忐忑的心情至今记忆犹新。看着社区里各种炫酷的角色皮肤、实用的功能增强MOD,却因为安…...