2017-05-07 39 views
0

在下面的一段蹦牀代碼中,我將從我的視圖中顯示的按鈕中調用 onclick = export(add,5)。如何確保此通話始終返回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次相同的輸出(換句話說,我要設置「出口」作爲一個純粹的功能)

回答

1

我不清楚你在問什麼,但你沒有理由依賴外部狀態,突變或重新分配這個功能。 ++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

+0

感謝Naomik。這完全回答了我的問題。我正在尋找使這個函數純粹沒有明確地清除x。但是,您是否具有與該功能等效的ECMAScript 5?這將是很大的幫助。 – vamsee

+0

@vamsee,我加了es5 – naomik

+0

非常感謝Naomik。我是認真的 :) – vamsee