"combine" 以功能方式在 javascript 中发挥作用?
To "combine" functions in javascript in a functional way?
我正在学习函数式编程,我想知道是否有办法 "combine" 像这样的函数:
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
combine(1); //1
combine(triple)(triple)(plusOne)(1); // 10
combine(plusOne)(triple)(isZero)(-1); // true
如果 para 是一个函数,它将 "combines" 函数转化为自身,如果不是,它将 return 最终结果。
谢谢!
您可以简单地在 return 值本身上调用该函数,例如:
plusOne(triple(triple(1))) // 10
isZero(triple(plusOne(-1))) // true
传承
这是一个数学概念,叫做 function composition。
f(x) = y
g(y) = z
g(f(x)) = z
(g•f)(x) = z
最后一行读作 "g of f of x equals z"。组合函数的伟大之处在于消除了点。请注意,在 g(f(x)) = z
中,我们采用 x
输入并获得 z
输出。这会跳过中间点 y
.
组合是创建 higher-order functions 并保持代码整洁的好方法。很明显我们为什么要在 Javascript 程序中使用它。
补偿
JavaScript 是一种多范式语言,具有丰富的功能支持。我们可以创建一个简单的 comp
函数,它结合了两个输入函数 g
和 f
,并生成 new 函数 -
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x)) // "g of f of x"
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
评价
triple(plusOne(1))
triple(2)
6
撰写
正如问题所暗示的,我们很可能想要组合两个以上的函数。下面我们编写 compose
,它采用 all
的输入函数,并使用上面的简单 comp
对它们进行 reduce
。如果没有给出函数,我们 return 空函数,identity
-
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x)) // "g of f of x"
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne) // any amount of funcs
console.log(myfunc(1))
评价
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
管道
你可以随心所欲地发挥创意。下面,我们写 pipe
允许我们的程序以舒适的从左到右的方向阅读 -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log) // 18
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log) // 31
表达式一的计算 -
f => pipe(f(1))
pipe(plusOne(1))
f => pipe(f(2))
pipe(triple(2))
f => pipe(f(6))
pipe(triple(6))
f => pipe(f(18))
pipe(console.log(18))
18
和表达式二-
f => pipe(f(3))
pipe(triple(3))
f => pipe(f(9))
pipe(plusOne(9))
f => pipe(f(10))
pipe(triple(10))
f => pipe(f(30))
pipe(plusOne(31))
f => pipe(f(31))
pipe(console.log(31))
31
相关技巧
柯里化函数和部分应用是与函数组合融为一体的概念。上面的pipe
在another Q&A中介绍为$
,这里再次演示-
const $ = x => // "pipe", or whatever name you pick
k => $ (k (x))
const add = x => y => // curried add
x + y
const mult = x => y => // curried mult
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
var combine = function (v) {
var fn = [];
function _f(v) {
if (typeof v === 'function') {
fn.push(v);
return _f;
} else {
return fn.reduce(function (x, f) { return f(x); }, v);
}
}
return _f(v);
};
var a, b;
console.log(combine(1)); //1
console.log(combine(triple)(triple)(plusOne)(1)); // 10
console.log(combine(plusOne)(triple)(isZero)(-1)); // true
console.log(a = combine(plusOne)); // function ...
console.log(b = a(triple)); // function ...
console.log(b(5)); // 18
console.log(combine(triple)(plusOne)(triple)(plusOne)(triple)(plusOne)(1)); // 40
// @naomik's examples
var f = combine(triple);
var g = combine(triple)(triple);
console.log(f(1)); // 3
console.log(g(1)); // 9 (not 6 as you stated)
在JavaScript.In某种意义上,也可以通过组合简单函数来构建复杂的功能,组合是函数的嵌套,将一个函数的结果作为输入传递给下一个函数。但是我们不会创建难以理解的嵌套量,而是创建一个高阶函数 compose(),它采用我们想要组合的所有函数,并且 returns 我们将在我们的应用程序中使用一个新函数.
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
const compose = (...fns) => x =>
fns.reduce((acc, cur) => {
return cur(acc);
}, x);
const withCompose = compose(triple, triple, isZero);
console.log(withCompose(1));
功能组合已经在其他答案中详细说明,主要是 ,所以我的 2 美分直接用于回答您的最新问题:
If the para is a function, it "combines" the function into itself, and if not it will return the final result. Thanks!
const chain = (g, f = x => x) =>
typeof g === 'function'
? (y) => chain(y, (x) => g(f(x)))
: f(g);
// ====
const triple = x => x * 3;
const inc = x => x + 1;
const isZero = x => x === 0;
console.log(
chain(inc)(triple)(isZero)(-1),
);
我正在学习函数式编程,我想知道是否有办法 "combine" 像这样的函数:
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
combine(1); //1
combine(triple)(triple)(plusOne)(1); // 10
combine(plusOne)(triple)(isZero)(-1); // true
如果 para 是一个函数,它将 "combines" 函数转化为自身,如果不是,它将 return 最终结果。 谢谢!
您可以简单地在 return 值本身上调用该函数,例如:
plusOne(triple(triple(1))) // 10
isZero(triple(plusOne(-1))) // true
传承
这是一个数学概念,叫做 function composition。
f(x) = y
g(y) = z
g(f(x)) = z
(g•f)(x) = z
最后一行读作 "g of f of x equals z"。组合函数的伟大之处在于消除了点。请注意,在 g(f(x)) = z
中,我们采用 x
输入并获得 z
输出。这会跳过中间点 y
.
组合是创建 higher-order functions 并保持代码整洁的好方法。很明显我们为什么要在 Javascript 程序中使用它。
补偿
JavaScript 是一种多范式语言,具有丰富的功能支持。我们可以创建一个简单的 comp
函数,它结合了两个输入函数 g
和 f
,并生成 new 函数 -
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x)) // "g of f of x"
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
评价
triple(plusOne(1))
triple(2)
6
撰写
正如问题所暗示的,我们很可能想要组合两个以上的函数。下面我们编写 compose
,它采用 all
的输入函数,并使用上面的简单 comp
对它们进行 reduce
。如果没有给出函数,我们 return 空函数,identity
-
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x)) // "g of f of x"
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne) // any amount of funcs
console.log(myfunc(1))
评价
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
管道
你可以随心所欲地发挥创意。下面,我们写 pipe
允许我们的程序以舒适的从左到右的方向阅读 -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log) // 18
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log) // 31
表达式一的计算 -
f => pipe(f(1))
pipe(plusOne(1))
f => pipe(f(2))
pipe(triple(2))
f => pipe(f(6))
pipe(triple(6))
f => pipe(f(18))
pipe(console.log(18))
18
和表达式二-
f => pipe(f(3))
pipe(triple(3))
f => pipe(f(9))
pipe(plusOne(9))
f => pipe(f(10))
pipe(triple(10))
f => pipe(f(30))
pipe(plusOne(31))
f => pipe(f(31))
pipe(console.log(31))
31
相关技巧
柯里化函数和部分应用是与函数组合融为一体的概念。上面的pipe
在another Q&A中介绍为$
,这里再次演示-
const $ = x => // "pipe", or whatever name you pick
k => $ (k (x))
const add = x => y => // curried add
x + y
const mult = x => y => // curried mult
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
var combine = function (v) {
var fn = [];
function _f(v) {
if (typeof v === 'function') {
fn.push(v);
return _f;
} else {
return fn.reduce(function (x, f) { return f(x); }, v);
}
}
return _f(v);
};
var a, b;
console.log(combine(1)); //1
console.log(combine(triple)(triple)(plusOne)(1)); // 10
console.log(combine(plusOne)(triple)(isZero)(-1)); // true
console.log(a = combine(plusOne)); // function ...
console.log(b = a(triple)); // function ...
console.log(b(5)); // 18
console.log(combine(triple)(plusOne)(triple)(plusOne)(triple)(plusOne)(1)); // 40
// @naomik's examples
var f = combine(triple);
var g = combine(triple)(triple);
console.log(f(1)); // 3
console.log(g(1)); // 9 (not 6 as you stated)
在JavaScript.In某种意义上,也可以通过组合简单函数来构建复杂的功能,组合是函数的嵌套,将一个函数的结果作为输入传递给下一个函数。但是我们不会创建难以理解的嵌套量,而是创建一个高阶函数 compose(),它采用我们想要组合的所有函数,并且 returns 我们将在我们的应用程序中使用一个新函数.
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
const compose = (...fns) => x =>
fns.reduce((acc, cur) => {
return cur(acc);
}, x);
const withCompose = compose(triple, triple, isZero);
console.log(withCompose(1));
功能组合已经在其他答案中详细说明,主要是
If the para is a function, it "combines" the function into itself, and if not it will return the final result. Thanks!
const chain = (g, f = x => x) =>
typeof g === 'function'
? (y) => chain(y, (x) => g(f(x)))
: f(g);
// ====
const triple = x => x * 3;
const inc = x => x + 1;
const isZero = x => x === 0;
console.log(
chain(inc)(triple)(isZero)(-1),
);