lodash curry 不适用于流返回的函数; lodash FP 够 FP 吗?
lodash curry does not work on function returned by flow; lodash FP enough for FP?
lodash 流函数是一个真正的组合函数,还是看起来像一个,但针对 运行 快速优化并牺牲了我期望的灵活性?我希望流向 return 一个我可以柯里化的函数,但它返回了一个使用 Javascript 的 arguments 关键字的函数。所以 curry 不能判断有未决参数,它只是立即被调用。
足够直观地工作:
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 的 each 中柯里化数据参数(我想要类似 eachMyArrayName 的快捷方式)。我是使用 curryRight 还是 lodash 对象占位符约定。
lodash FP 是否只是为了让 lodash 函数自动 curriable?还是我做错了什么,它可以作为主要的函数式编程助手使用?
编辑:
如果我愿意,我可以像这样包装函数,但这似乎违背了元编程让代码看起来像样板的目的。
add1AndExclamV2 = FP.curry(function(x, y) {
return addAndExclam(x, y)
})(1)
add1AndExclamV2(2)
“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!"
看起来 ramda 做了我觉得很直观的事情。它在我的项目中又增加了 1.2mb,但我想它可以用来或多或少地替换 lodash。
这只是基本的函数组合。 Lodash "flow" 和 Rambda "pipe" 可能发现很难命名这些函数,因为它们不适合通用。它们 "real" 与您在短语 "real compose function".
中使用 real 一词的方式不同
您可以使用 comp2
将二元函数与一元函数组合在一起 – 问题是,"binary" 函数必须采用柯里化形式,而不是采用元组
let f = x => y => ...
而不是
let f = (x,y) => ...
回想一下,函数式编程起源于 the lambda calculus,其中没有接受除 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!"
我鼓励您使用 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!"
关于您的评论:
I think if I wanted to compose a special function where one of the nested functions took two args, I would write it out
好主意。如果您发现自己在四处寻找内置过程(由您的语言或某些库提供),那应该已经向您表明您应该首先尝试将其写出来。至少要确认自己是否正确理解了自己的需求。
这是完全可以接受的
const addAndExclam = (x,y) => exclam (add (x,y))
这也是
const addAndExclam = x => y => exclam (add (x,y))
如果以后学习comp2
,看到能把代码描述的好一点,那时候就可以实现了
const addAndExclam = comp2 (exclam) (curry (add))
lodash 流函数是一个真正的组合函数,还是看起来像一个,但针对 运行 快速优化并牺牲了我期望的灵活性?我希望流向 return 一个我可以柯里化的函数,但它返回了一个使用 Javascript 的 arguments 关键字的函数。所以 curry 不能判断有未决参数,它只是立即被调用。
足够直观地工作:
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 的 each 中柯里化数据参数(我想要类似 eachMyArrayName 的快捷方式)。我是使用 curryRight 还是 lodash 对象占位符约定。
lodash FP 是否只是为了让 lodash 函数自动 curriable?还是我做错了什么,它可以作为主要的函数式编程助手使用?
编辑:
如果我愿意,我可以像这样包装函数,但这似乎违背了元编程让代码看起来像样板的目的。
add1AndExclamV2 = FP.curry(function(x, y) {
return addAndExclam(x, y)
})(1)
add1AndExclamV2(2)
“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!"
看起来 ramda 做了我觉得很直观的事情。它在我的项目中又增加了 1.2mb,但我想它可以用来或多或少地替换 lodash。
这只是基本的函数组合。 Lodash "flow" 和 Rambda "pipe" 可能发现很难命名这些函数,因为它们不适合通用。它们 "real" 与您在短语 "real compose function".
中使用 real 一词的方式不同您可以使用 comp2
将二元函数与一元函数组合在一起 – 问题是,"binary" 函数必须采用柯里化形式,而不是采用元组
let f = x => y => ...
而不是
let f = (x,y) => ...
回想一下,函数式编程起源于 the lambda calculus,其中没有接受除 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!"
我鼓励您使用 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!"
关于您的评论:
I think if I wanted to compose a special function where one of the nested functions took two args, I would write it out
好主意。如果您发现自己在四处寻找内置过程(由您的语言或某些库提供),那应该已经向您表明您应该首先尝试将其写出来。至少要确认自己是否正确理解了自己的需求。
这是完全可以接受的
const addAndExclam = (x,y) => exclam (add (x,y))
这也是
const addAndExclam = x => y => exclam (add (x,y))
如果以后学习comp2
,看到能把代码描述的好一点,那时候就可以实现了
const addAndExclam = comp2 (exclam) (curry (add))