Ramda函数组合实践:实现无点式关联cost属性至目标对象
实现无点式的成本关联函数(Ramda)
很高兴看到你在深挖Ramda和函数式编程的核心概念!把零散的操作整合成**无点式(Point-free)**的组合函数,确实是函数式风格的精华所在。我来帮你梳理出优雅的实现方案:
核心思路拆解
我们的目标是:给一个目标对象(比如aaa),自动从kdlJsonObj中匹配对应name的项,取出cost并关联到目标对象上,全程用组合式的写法完成,不需要显式声明参数。
这里的关键是:我们需要同时用到原目标对象和从目标对象推导出来的cost值,所以单纯的compose/pipe不足以处理双输入的场景,Ramda的converge函数正好能解决这个问题——它可以让我们从同一个输入衍生出多个值,再传给合并函数。
完整实现代码
// API返回的对象 const kdlJsonObj = [ {name: 'AAA COOPER TRANSPORTATION', cost: 33}, {name: 'OLD DOMINION FREIGHT LINE, INC', cost: 22}, {name: 'ROADRUNNER TRANSPORTATION SERVICES', cost: 31} ] // 待关联的目标对象 const aaa = {shortName: 'AAA Cooper', name: 'AAA COOPER TRANSPORTATION' } const odlf = {shortName: 'Old Dominion', name: 'OLD DOMINION FREIGHT LINE, INC'} const rr = {shortName: 'Road Runner', name: 'ROADRUNNER TRANSPORTATION SERVICES'} // 定义无点式的组合函数 const addCostFromKdl = R.converge( // 合并函数:把cost关联到原对象上 R.assoc('cost'), [ // 分支1:从目标对象推导cost的流程(用pipe更符合阅读顺序) R.pipe( R.prop('name'), // 取出目标对象的name R.propEq('name'), // 创建匹配name的断言函数 R.find(R.__, kdlJsonObj), // 用断言在kdl数组中找匹配项(R.__是占位符) R.prop('cost') // 取出匹配项的cost ), // 分支2:直接返回原目标对象(R.identity就是返回输入本身) R.identity ] ) // 调用测试 addCostFromKdl(aaa) // => {shortName: "AAA Cooper", name: "AAA COOPER TRANSPORTATION", cost: 33} addCostFromKdl(odlf) // => {shortName: "Old Dominion", name: "OLD DOMINION FREIGHT LINE, INC", cost: 22} addCostFromKdl(rr) // => {shortName: "Road Runner", name: "ROADRUNNER TRANSPORTATION SERVICES", cost: 31}
代码解释
R.converge的作用:它接收两个参数——一个合并函数,和一个函数数组。数组里的每个函数都会接收同一个输入(这里就是目标对象),然后把各自的结果传给合并函数。- 分支1的
pipe流程:从左到右执行,完全贴合我们的思考逻辑,而且全程是无点式的,没有显式声明参数。 R.__占位符:用来告诉Ramda,我们要延迟传递某个参数,这里就是把find的断言参数留到pipe的前一步生成后再传入。
拓展:让函数更通用
如果以后需要切换不同的API数据源,可以把kdlJsonObj变成参数,让函数复用性更强:
const createCostAdder = (kdlData) => R.converge( R.assoc('cost'), [ R.pipe( R.prop('name'), R.propEq('name'), R.find(R.__, kdlData), R.prop('cost') ), R.identity ] ) // 用不同数据源生成对应的关联函数 const addCostFromKdl = createCostAdder(kdlJsonObj) const addCostFromAnotherSource = createCostAdder(anotherKdlData)
你原来尝试的问题点
你之前在compose里写R.find(name, kdlJsonObj)是行不通的,因为compose要求每个中间函数都是一元函数(只接收一个参数),而R.find是二元函数(需要断言和数组)。用R.__占位符或者curry化之后,才能把它适配成一元函数的形式。
内容的提问来源于stack exchange,提问作者nzaleski




