lodash咖喱不适用于流返回的功能; lodash FP足够FP吗?

时间:2016-08-19 13:56:48

标签: javascript functional-programming lodash curry

lodash流程功能是真正的组合功能,还是看起来像是一个功能,但是经过优化可以快速运行并牺牲我期望的灵活性?我希望flow能够返回一个我可以进行curry的函数,但是它返回了一个使用Javascript"的arguments关键字的函数。因此,咖喱不能告诉有待处理的参数,而且它会立即被调用。

足够直观地工作:

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<r;)t=n[u].call(this,t);
    return t
}
*/
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)

&#34;!3&#34;`

2 个答案:

答案 0 :(得分:0)

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!"

看起来ramda对我来说很直观。它为我的项目增加了另外1.2mb,但我想它可以用来或多或少取代lodash。

答案 1 :(得分:0)

这只是基本的功能构成。 Lodash&#34; flow&#34;和Rambda&#34; pipe&#34;可能发现很难命名这些功能,因为它们不是通用的。他们不是真实的&#34;与在短语&#34;真正的撰写函数&#34;中使用 real 这个词的方式相同。

您可以使用comp2使用一元函数编写二元函数 - catch是&#34; binary&#34;函数必须是curry形式而不是取元组

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

而不是

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

回想一下,函数式编程的根源在于the lambda calculus,其中没有一个函数除了1参数之外还有其它东西。

&#13;
&#13;
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!"
&#13;
&#13;
&#13;

我鼓励您使用substitution model来查看表达式的评估方式

将所有类型放在一起可以帮助您更有效地推理该计划

// 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!"

关于你的评论:

  

我想如果我想编写一个特殊的函数,其中一个嵌套函数有两个args,我会把它写出来

好主意。如果您发现自己四处寻找内置程序(由您的语言或某些库提供),那么您应该首先尝试将其写出来。至少要确认自己是否正确理解了自己的需求。

这是完全可以接受的

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

这是

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

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

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