将 javascript 和 typescript 中的函数式编程与 Ramda 结合使用,我经常发现自己编写的代码如下:
const myFun = c => {
const myId = c.id
const value = pipe(
getAnotherOtherPropOfC,
transformToArray,
mapToSomething,
filterSomething,
// ... N other transformations
// ok now I need myId and also the result of the previous function
chainMyIdWithResultOfPreviousFunction(myId)
)(c)
return value
}
注意创建 const myId
如何打破无点样式。我想写 myFun
这样就不需要显式 c
了。所以像:
const myFun = pipe(....)
我想知道是否有一种更实用、更易读的方式来做这样的事情。
最佳答案
可以做到吗?当然。 应该这样做吗?不是很清楚。
这是上面的无点版本,使用lift
:
const getAnotherOtherPropOfC = prop ('x')
const transformToArray = split (/,\s*/)
const mapToSomething = map (Number)
const filterSomething = filter (n => n % 2 == 1)
const square = (n) => n * n
const chainMyIdWithResultOfPreviousFunction = (id) => (arr) => `${id}: [${arr}]`
const myFun = lift (chainMyIdWithResultOfPreviousFunction) (
prop ('id'),
pipe(
getAnotherOtherPropOfC,
transformToArray,
mapToSomething,
filterSomething,
map (square)
)
)
console .log (
myFun ({id: 'foo', x: '1, 2, 3, 4, 5'}) // => 'foo: [1,9,25]'
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const {prop, split, map, filter, lift, pipe} = R </script>
lift
是比 Ramda 的 converge
更符合 FP 标准的函数(与 useWith
一起提供了制作无点解决方案的方法,通常以牺牲可读性为代价。)lift
在应用于函数时与 converge
重叠,但被设计为对于一元函数,其中 converge
处理多元函数。
这并不可怕。但与原版相比,它的唯一优势是它没有积分。如果您尝试将其扩展到该管道中的中间函数,它将变得非常丑陋。
我的看法是,无点有时可以带来更清晰、更易于阅读和更易于维护的代码。但是,如果不这样做,就没有理由不计分。
这并不是说 point-free 本质上比 pointed 代码更实用。我认为这个想法最初是对其他语言的一种 Haskell 嫉妒。 Haskell 被认为是一种理想化的 FP 语言,它恰好是一种自然而然地出现无点的语言。但这至少部分是巧合。
我的标准示例是 const sum = reduce(add, 0)
比 const sum = (xs) => xs.reduce(add, 0)
。它还非常清楚地表明了与 const product = reduce(multiply, 1)
或 const all = reduce(and, true)
的相似之处。但随着您变得越来越复杂,或者当您需要重用中间计算时(正如 Bergi 指出的那样),无点代码通常会成为一种负担。
关于此版本是否是对原始版本的改进,我在这里没有真正的意见。如果是这样,那只是一个小问题。进一步携带它会显着降低可读性。
关于javascript - 在管道中重用变量的功能方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58199319/