2015-11-26 19 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