2015-11-26 22 views
3

我有我转换的字符串:如何合并2个组合物与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" 

我'd想知道的是,是否有更清洁更有效的方法来将replaceTailupperHead结合起来,所以我只能遍历一次字符串?

JSBin example

回答

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" 

这是一种有趣的方式来组合功能。我不确定为什么要求在replace之前抓住tail。看起来像replace函数可以更新,只是通过正则表达式替换任何-通过启动字符。如果是这种情况,我们可以联合replace

还有一件事。 Profunctor的dimap功能实例非常简洁,镜头也是如此。一起使用它们,我们可以将字符串转换为一个数组,然后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" 
+0

大规模+1从资料库中的'mconcat'就是我一直在寻找。 Dimap看起来有趣,将不得不进一步深入:) – cmdv

3

Brian的解决方案非常棒。

注意,您可以在纯Ramda使用lift这样做mconcat

const replaceMe = _.lift(_.concat)(upperHead, replaceTail) 
+0

啊很酷我正在搜索一段时间的文档,找不到哪个运营商使用谢谢 – cmdv