Tho*_*ggi 8 javascript dictionary functional-programming lodash ramda.js
我正在学习Ramda
,我有点困惑如何在lodash
下面使用构建这个链Ramda
.Ramda
返回它的操作而不是实际值的函数,这似乎是函数式编程的焦点,但是在这个例子中我有第二个参数localRegex
不是主要参数.似乎在没有包装Ramda
函数和使用.apply()
或.call()
将包装的函数参数传播给函数的情况下完全复制它是不可能的Ramda
,这似乎比使用更复杂lodash
.
var _ = require("lodash")
var R = require("ramda")
var localRegex = /^.\.\/|^.\/|^\//
function getRecursiveDeps(deps, localRegex){
return _.chain(deps)
.map(function(dep){
return dep.source.value
})
.filter(function(dep){
return dep.match(localRegex)
})
.value()
}
var items = [
{
"source": {
"value": "./foo"
}
},
{
"source": {
"value": "bar"
}
}
]
console.log(getRecursiveDeps(items, localRegex))
Run Code Online (Sandbox Code Playgroud)
这是我得到的,它不起作用.
var getRecursiveDeps = R.chain(
R.map(function(dependency){
return dependency.source.value
}),
R.filter(function(value){
return value.match(localRegex)
})
)
Run Code Online (Sandbox Code Playgroud)
有没有办法Ramda
使用主变量进行链接并传递下去localRegex
?有没有办法复制getRecursiveDeps
使用lodash
的Ramda
?
有一个关于如何谈论很多的Ramda
是功能和underscore
与lodash
不是.但在这种情况下,getRecursiveDeps
是一个返回值的函数lodash
.当你创建这样的函数lodash
或者underscore
结果是相同的时候,在包装它时会有更多的工作,在这种情况下,使用Ramda
的是Lodash
什么?
R.chain
做一些完全不同的事情_.chain
.根据当前的文档,(a -> [b]) -> [a] -> [b]
它的类型是,虽然它的实际类型更为通用.将其视为"平面地图"功能.
你真正想要的是R.compose
它或它从左到右的等价物R.pipe
.
如果函数的目标是找到本地依赖项,那么将模式嵌入函数中似乎是合适的.我会写:
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps =
R.pipe(R.map(R.path(['source', 'value'])),
R.filter(R.test(/^[.]{0,2}[/]/)));
getLocalDeps(items); // => ['./foo']
Run Code Online (Sandbox Code Playgroud)
我对名称感到有点困惑,getRecursiveDeps
因为函数不是递归的.getLocalDeps
似乎更合适.
如果您想参数化模式,我建议getLocalDeps
分成小块:
// isLocal :: String -> Boolean
const isLocal = R.test(/^[.]{0,2}[/]/);
// getDeps :: [{ source :: { value :: String }}] -> [String]
const getDeps = R.map(R.path(['source', 'value']));
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps = R.pipe(getDeps, R.filter(isLocal));
Run Code Online (Sandbox Code Playgroud)
然后,您可以根据这些构建块定义其他函数:
// getNonLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getNonLocalDeps = R.pipe(getDeps, R.reject(isLocal));
// getLocalJsonDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalJsonDeps = R.pipe(getLocalDeps, R.filter(R.test(/[.]json$/)));
Run Code Online (Sandbox Code Playgroud)
这样做的另一种方法,无积分并保留您现有的 API 是这样的:
// getLocalDeps :: [{ source :: { value :: String }}] -> RegExp -> [String]
const getLocalDeps = R.useWith(
R.flip(R.call),
R.map(R.path(['source', 'value'])),
R.pipe(R.unary(R.test), R.filter)
);
localDeps(items, localRegex); //=> ["./foo"]
Run Code Online (Sandbox Code Playgroud)
函数的最后一行对我来说感觉有点不幸,这个问题让我打开了一个关于恢复最近对库的一些更改的问题。有几种可以使用的变体:
// ...
R.pipe(regex => item => R.test(regex, item), R.filter)
//...
Run Code Online (Sandbox Code Playgroud)
或者
// ...
regex => R.filter(R.test(regex))
//...
Run Code Online (Sandbox Code Playgroud)
但是在最近对 Ramda 进行更改之前,它会很简单
// ...
R.pipe(R.test, R.filter)
//...
Run Code Online (Sandbox Code Playgroud)
不过,有一件事是 Ramda 努力使参数保持在逻辑顺序中:那些不太可能改变的先于那些更有可能改变的。考虑到这一点,我更喜欢这样的事情:
// getLocalDeps :: RegExp -> [{ source :: { value :: String }}] -> [String]
var getLocalDeps2 = R.useWith(
R.call,
R.pipe(R.unary(R.test), R.filter),
R.map(R.path(['source', 'value']))
);
localDeps2(localRegex, items); //=> ["./foo"]
Run Code Online (Sandbox Code Playgroud)
那感觉仍然更干净。此外,它允许您预定义函数并单独使用它:
myDeps = localDeps2(localRegex);
myDeps(items); //=> ["./foo"]
Run Code Online (Sandbox Code Playgroud)
这是 Ramda 的一个很好的部分。
归档时间: |
|
查看次数: |
7355 次 |
最近记录: |