Export Function需要设置为纯函数
Export Function needs to be set as a pure function
在下面的一段 Trampoline 代码中,我将调用
onclick = export(add,5)
来自我视图中的按钮。如何确保此调用始终 returns 5
的值而不取消注释下面代码中 //x=0
所在的行?
var x = 0;
function repeat(operation, num) {
return function () {
if (num <= 0) {
console.log(x);
// x=0;
return;
}
operation();
return repeat(operation, --num);
}
}
function trampoline(fn) {
while (fn && typeof fn === 'function') {
fn= fn();
}
}
this.export = function (operation, num) {
trampoline(function () {
return repeat(operation, num);
});
}
function add()
{
++x;
}
基本上,我想要一个解决方案,其中我的变量 x 的范围将确保程序在执行 n 次时总是 returns 相同的输出(换句话说,我想设置 'export' 作为纯函数)
我不太清楚你在问什么,但你没有理由依赖外部状态、突变或重新分配此功能。 ++x
和 --n
是函数式编程幻想世界中的噩梦——您将希望以几乎所有常见模式避免它们。
// checking typeof === 'function' is not really reliable in functional programming
// function return values are perfectly good return types
// use data abstraction to mark tail calls
const trampoline = {
bounce: (f, x) =>({ isBounce: true, f, x}),
run: t => {
while (t && t.isBounce)
t = t.f(t.x)
return t
}
}
// local binding, no mutation, just return x + 1
const add = x => x + 1
// bounced repeat
const repeatAux = (f,n) => x =>
n === 0 ? x : trampoline.bounce(repeatAux(f, n - 1), f(x))
// this is the function you export
// it runs trampolined repeatAux with initial state of 0
const repeat = (f,n) =>
trampoline.run(repeatAux(f,n)(0))
// all calls to repeat are pure and do not require external state, mutation, or reassignment
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7
// repeat 1 million times to show trampoline works
console.log(repeat(add, 1e6)) // 1000000
ES5,按要求
var trampoline = {
bounce: function (f, x) {
return ({ isBounce: true, f, x})
},
run: function (t) {
while (t && t.isBounce)
t = t.f(t.x)
return t
}
}
var add = function (x) { return x + 1 }
var repeatAux = function (f,n) {
return function (x) {
return n === 0
? x
: trampoline.bounce(repeatAux(f, n - 1), f(x))
}
}
var repeat = function (f,n) {
return trampoline.run(repeatAux(f,n)(0))
}
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 1e6)) // 1000000
在下面的一段 Trampoline 代码中,我将调用
onclick = export(add,5)
来自我视图中的按钮。如何确保此调用始终 returns 5
的值而不取消注释下面代码中 //x=0
所在的行?
var x = 0;
function repeat(operation, num) {
return function () {
if (num <= 0) {
console.log(x);
// x=0;
return;
}
operation();
return repeat(operation, --num);
}
}
function trampoline(fn) {
while (fn && typeof fn === 'function') {
fn= fn();
}
}
this.export = function (operation, num) {
trampoline(function () {
return repeat(operation, num);
});
}
function add()
{
++x;
}
基本上,我想要一个解决方案,其中我的变量 x 的范围将确保程序在执行 n 次时总是 returns 相同的输出(换句话说,我想设置 'export' 作为纯函数)
我不太清楚你在问什么,但你没有理由依赖外部状态、突变或重新分配此功能。 ++x
和 --n
是函数式编程幻想世界中的噩梦——您将希望以几乎所有常见模式避免它们。
// checking typeof === 'function' is not really reliable in functional programming
// function return values are perfectly good return types
// use data abstraction to mark tail calls
const trampoline = {
bounce: (f, x) =>({ isBounce: true, f, x}),
run: t => {
while (t && t.isBounce)
t = t.f(t.x)
return t
}
}
// local binding, no mutation, just return x + 1
const add = x => x + 1
// bounced repeat
const repeatAux = (f,n) => x =>
n === 0 ? x : trampoline.bounce(repeatAux(f, n - 1), f(x))
// this is the function you export
// it runs trampolined repeatAux with initial state of 0
const repeat = (f,n) =>
trampoline.run(repeatAux(f,n)(0))
// all calls to repeat are pure and do not require external state, mutation, or reassignment
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7
// repeat 1 million times to show trampoline works
console.log(repeat(add, 1e6)) // 1000000
ES5,按要求
var trampoline = {
bounce: function (f, x) {
return ({ isBounce: true, f, x})
},
run: function (t) {
while (t && t.isBounce)
t = t.f(t.x)
return t
}
}
var add = function (x) { return x + 1 }
var repeatAux = function (f,n) {
return function (x) {
return n === 0
? x
: trampoline.bounce(repeatAux(f, n - 1), f(x))
}
}
var repeat = function (f,n) {
return trampoline.run(repeatAux(f,n)(0))
}
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 1e6)) // 1000000