如何将2个合成与Ramda.js合并

cmd*_*mdv 4 javascript functional-programming ramda.js

我有一个我正在转换的字符串:

"replace-me-correctly" => "Replace me correctly"

我的代码使用Ramda.js:

const _ = R; //converting Ramda.js to use _

const replaceTail = _.compose(_.replace(/-/g, ' '), _.tail);
const upperHead = _.compose(_.toUpper ,_.head);

const replaceMe = (str) => _.concat(upperHead(str) , replaceTail(str));

replaceMe("replace-me-correctly"); // "Replace me correctly"
Run Code Online (Sandbox Code Playgroud)

我想知道的是,如果有更清洁更有效的方式结合replaceTail,upperHead所以我只遍历字符串一次?

JSBin的例子

Bri*_*ian 6

不确定只遍历字符串一次.听起来很难.我会提供一些有趣和洞察力的不同方法.

函数的monoid实例将通过使用给定的参数运行它们并连接它们的结果来连接每个函数(它们必须返回相同的类型才能正确组合).replaceMe正是这样做,所以我们可以使用mconcat.

const { compose, head, tail, replace, toUpper } = require('ramda')
const { mconcat } = require('pointfree-fantasy')

// fun with monoids
const replaceTail = compose(replace(/-/g, ' '), tail)
const upperHead = compose(toUpper, head)
const replaceMe = mconcat([upperHead, replaceTail])

replaceMe("replace-me-correctly")
//=> "Replace me correctly"
Run Code Online (Sandbox Code Playgroud)

这是组合功能的有趣方式.我不确定为什么要求在tail之前抓住replace.似乎replace可以更新函数以-通过正则表达式替换任何过去的起始字符.如果是这种情况,我们可以内联replace.

还有一件事.dimap来自Profunctor 的功能实例非常整洁,镜头也是如此.将它们一起使用,我们可以将字符串转换为数组,然后toUpper只转换为第0个索引.

const { curry, compose, split, join, head, replace, toUpper } = require('ramda')
const { mconcat } = require('pointfree-fantasy')
const { makeLenses, over } = require('lenses')
const L = makeLenses([])

// fun with dimap
const dimap = curry((f, g, h) => compose(f,h,g))
const asChars = dimap(join(''), split(''))
const replaceMe = compose(replace(/-/g, ' '), asChars(over(L.num(0), toUpper)))

replaceMe("replace-me-correctly")
//=> "Replace me correctly"
Run Code Online (Sandbox Code Playgroud)