lodash咖喱不适用于流量返回的功能; FP足够FP吗? [英] lodash curry does not work on function returned by flow; lodash FP enough for FP?

查看:109
本文介绍了lodash咖喱不适用于流量返回的功能; FP足够FP吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

lodash流函数是一个真正的组合函数,还是它看起来像一个函数,但它被优化以便快速运行并牺牲我期望的灵活性?我期望流程返回一个我可以咀嚼的函数,但是它却给出了一个使用Javascript参数关键字的函数。因此,咖喱不能说明有没有悬而未决的争论,而是立即被调用。



足够直观地工作:



var add = function(x,y){return x + y};
var exclam = function(x){return x.toString()+!; }
exclam(1)//1!
add(1,2)// 3
var add1 = FP.curry(add)(1);
add1(4)// 5
var add1AndExclam = FP.flow([add1,exclam])
add1AndExclam(2)//3!



非直观的结果:

addAndExclam = FP.flow([add,exclam ])
// function(){var t = arguments,e = t [0]; if(i&& 1> t.length&& yi(e)& e.length> ; = 200)return i.plant(e).value(); for(var u = 0,t = r?n [u] .apply(this,t):e; ++ u addAndExclam(1,2)//3!
add1AndExclamV2 = FP.curry(addAndExclam)(1)//NaN!



查找另一个库来帮助功能性编程范例?我应该鞭打自己的作品吗?我使用了lodash,因为它已经在我的项目中了。这些文档使得它看起来像流应该是lodash的组成。



我也发现很难在lodash的每一个数据参数中嵌入数据参数(我希望像eachMyArrayName捷径)。无论我使用curryRight还是lodash对象占位符约定。



lodash FP仅用于使lodash函数自动变为可压缩吗?或者我做错了什么,它可以作为主要的函数编程助手吗?

编辑:

如果我想我可以包装这样的功能,但它似乎打败了元编程的目的有样板代码。



add1AndExclamV2 = FP.curry(function(x,y){return addAndExclam(x,y)})(1)
add1AndExclamV2(2)
3!

解决方案

这只是基本的功能组合。 Lodash流和Rambda管道可能很难命名这些函数,因为它们不是通用的。它们不像真正的真正的一样使用真正的合成功能。



你可以编写一个二元函数的一元函数使用 comp2 - catch是,binary函数必须是curry形式而不是采用元组

  let f = x => y => ... 

而不是

  let f =(x,y)=> ... 

回想一下,函数式编程的根源在 lambda微积分,其中不存在除1参数以外的其他函数。



  const curry = f => x => y => f(x,y)const comp = f => g => x => f(g(x))const comp2 = comp(comp)(comp)var add = function(x,y){return x + y}; var exclam = function(x){return x.toString()+! ; } console.log(exclam(1))//1!console.log(add(1,2))// 3var add1 = curry(add)(1)console.log(add1(4))// 5var addAndExclam = comp2(exclam)(curry(add))console.log(addAndExclam(1)(2))//3! 



我鼓励您使用替换模型,以查看表达式的评估结果。




一切都可以帮助你更有效地推理程序。

  //咖喱::((a,b) - > c) - > a  - > b  - > c 
const curry = f => x => y => f(x,y)

// comp ::(b - > c) - > (a - > b) - > (a - > c)
const comp = f => g => x => f(g(x))

// comp2 ::(c - > d) - > (a→b→c)→> (a - > b - > d)
const comp2 = comp(comp)(comp)

// add ::(Number,Number) - > Number
var add = function(x,y){return x + y};

// exclam :: Number - > String
var exclam = function(x){return x.toString()+!; }

console.log(exclam(1))//1!
console.log(add(1,2))// 3

// add1 :: Number - > Number
var add1 = curry(add)(1)
console.log(add1(4))// 5

// addAndExlam :: Number - >数字 - > String
var addAndExclam = comp2(exclam)(curry(add))
console.log(addAndExclam(1)(2))//3!






关于您的评论:


我想如果我想编写一个特殊的函数,其中一个嵌套函数需要两个参数,我会写出来

好主意。如果您发现自己在寻找内置过程(由您的语言或某个库提供),那么这应该已经成为您应该尝试首先写出来的指示器。至少要确认自己是否正确理解了你的需求。



这完全可以接受

  const addAndExclam =(x,y)=> exclam(add(x,y))

所以这是

  const addAndExclam = x => y => exclam(add(x,y))

如果您稍后了解 comp2 并且看到它可以更好地描述代码,那么你可以在当时实现它

  const addAndExclam = comp2(exclam)(curry(add))


Is the lodash flow function a real compose function, or is it something that looks like one, but is optimized to run fast and sacrifices the flexibility I'd expect? I expected flow to return a function I could curry, but instead it gave back a function that uses Javascript's arguments keyword. So curry can't tell that there are pending arguments, and it just gets invoked immediately.

Working intuitively enough:

var add = function(x, y) { return x + y }; var exclam = function(x) { return x.toString() + "!"; } exclam(1) // "1!" add(1,2) // 3 var add1 = FP.curry(add)(1); add1(4) // 5 var add1AndExclam = FP.flow([add1, exclam]) add1AndExclam(2) // "3!"

Non-intuitive result:

addAndExclam = FP.flow([add, exclam]) // function(){var t=arguments,e=t[0];if(i&&1==t.length&&yi(e)&&e.length>=200)return i.plant(e).value();for(var u=0,t=r?n[u].apply(this,t):e;++u<r;)t=n[u].call(this,t);return t} addAndExclam(1,2) // "3!" add1AndExclamV2 = FP.curry(addAndExclam)(1) // "NaN!"

Is it overkill to look for another library to help with functional programming paradigms? Should I just whip up my own compose? I used lodash because it was already in my project. The documentation makes it look like flow should be lodash's compose.

I've also found it really difficult to curry the data argument in lodash's each (I wanted something like an eachMyArrayName shortcut). Whether I use curryRight or the lodash object placeholder convention.

Is lodash FP just for making lodash functions auto curriable? Or am I doing something wrong, and it is usable as the main functional programming helper?

Edit:

If I want to I can wrap the function like this, but it seems to defeat the purpose of meta programming to have boilerplate looking code.

add1AndExclamV2 = FP.curry( function(x, y) { return addAndExclam(x, y) } )(1) add1AndExclamV2(2) "3!"

解决方案

This is just basic function composition. Lodash "flow" and Rambda "pipe" probably found it difficult to name these functions because they're not suitably generic. They're not "real" the same way you use the word real in the phrase "real compose function".

You can compose a binary function with a unary function using comp2 – the catch is, the "binary" function must be in curried form instead of taking a tuple

let f = x => y => ... 

instead of

let f = (x,y) => ...

Recall that functional programming has its roots in the lambda calculus where there is no such thing as a function that takes anything other than 1 argument.

const curry = f => x => y => f (x,y)
const comp = f => g => x => f (g (x))
const comp2 = comp (comp) (comp)

var add = function(x, y) { return x + y };
var exclam = function(x) { return x.toString() + "!"; }

console.log(exclam (1)) // "1!"
console.log(add (1,2)) // 3

var add1 = curry (add) (1)
console.log(add1 (4)) // 5

var addAndExclam = comp2 (exclam) (curry (add))
console.log(addAndExclam (1) (2)) // "3!"

I encourage you to use the substitution model to see how the expression evaluates


Putting types on everything helps you reason about the program more effecitvely

// curry :: ((a,b) -> c) -> a -> b -> c
const curry = f => x => y => f (x,y)

// comp :: (b -> c) -> (a -> b) -> (a -> c)
const comp = f => g => x => f (g (x))

// comp2 :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
const comp2 = comp (comp) (comp)

// add :: (Number,Number) -> Number
var add = function(x, y) { return x + y };

// exclam :: Number -> String
var exclam = function(x) { return x.toString() + "!"; }

console.log(exclam (1)) // "1!"
console.log(add (1,2)) // 3

// add1 :: Number -> Number
var add1 = curry (add) (1)
console.log(add1 (4)) // 5

// addAndExlam :: Number -> Number -> String
var addAndExclam = comp2 (exclam) (curry (add))
console.log(addAndExclam (1) (2)) // "3!"


Regarding your comment:

I think if I wanted to compose a special function where one of the nested functions took two args, I would write it out

Good idea. If you find yourself looking around for a built-in procedure (provided by your language or some library), that should already be an indicator to you that you should try to write it out first. At least confirm with yourself that you're understanding your needs correctly.

This is perfectly acceptable

const addAndExclam = (x,y) => exclam (add (x,y))

And so is this

const addAndExclam = x => y => exclam (add (x,y))

If you later learn about comp2 and see that it could describe the code a little better, then you can implement it at that time

const addAndExclam = comp2 (exclam) (curry (add))

这篇关于lodash咖喱不适用于流量返回的功能; FP足够FP吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆