简体   繁体   English

lodash curry 对 flow 返回的函数不起作用; lodash FP 够 FP 吗?

[英]lodash curry does not work on function returned by flow; lodash FP enough for FP?

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? lodash 流函数是真正的 compose 函数,还是看起来像一个函数,但经过优化以快速运行并牺牲了我期望的灵活性? I expected flow to return a function I could curry, but instead it gave back a function that uses Javascript's arguments keyword.我希望 flow 返回一个我可以使用的函数,但它返回了一个使用 Javascript 参数关键字的函数。 So curry can't tell that there are pending arguments, and it just gets invoked immediately.所以 curry 无法判断有待处理的参数,它会立即被调用。

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.我使用 lodash 因为它已经在我的项目中了。 The documentation makes it look like flow should be lodash's compose.文档使它看起来像是流应该是 lodash 的组合。

I've also found it really difficult to curry the data argument in lodash's each (I wanted something like an eachMyArrayName shortcut).我还发现在 lodash 的 each 中对 data 参数进行柯里化真的很困难(我想要一个类似 eachMyArrayName 的快捷方式)。 Whether I use curryRight or the lodash object placeholder convention.我是否使用 curryRight 或 lodash 对象占位符约定。

Is lodash FP just for making lodash functions auto curriable? lodash FP 只是为了使 lodash 函数可自动运行吗? 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!"` “3!”`

var myAdd = function(x, y) { return x + y; }; var exclam = function(x) { return x.toString() + '!'; }; var addSclam = pipe(myAdd, exclam); addSclam(1,2); // "3!" var add1Sclam = curry( addSclam )(1); add1Sclam(500); // "501!"

It looks like ramda does what would have been intuitive to me.看起来 ramda 做了我认为很直观的事情。 It adds another 1.2mb to my project, but I guess it could be used to more or less replace lodash.它为我的项目又增加了 1.2mb,但我想它或多或少可以用来替代 lodash。

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. Lodash “flow” 和 Rambda “pipe” 可能发现很难命名这些函数,因为它们不适合通用。 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您可以使用comp2将二元函数与一元函数comp2 ——问题是,“二元”函数必须采用comp2形式,而不是采用元组

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.回想一下,函数式编程的根源在于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)) // 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我想如果我想编写一个特殊函数,其中一个嵌套函数接受两个 args,我会把它写出来

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如果你后来了解了comp2并且看到它可以更好地描述代码,那么你可以在那个时候实现它

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM