存儲傳遞風格

存儲傳遞風格是一種技術,用來建模可變狀態英語State (computer science)而不用使用全局變量[1][2]。它通常出現在將指令式程序轉換成純函數式程序的場合。

實例

編輯

考慮如下這個用「非存儲傳遞風格」書寫的JavaScript程序:

var lastWasA = false

// treebin表示字符串的二叉树。
// treebin要么是一个字符串,
// 要么是{l : <treebin>, r: <treebin>}。

// 对这个树的叶子的中序遍历含有'a'跟随着'b'吗?
function aThenB(treebin) {
  if (typeof(treebin) === "string") {
    if (treebin === "a") {
      lastWasA = true;
      return false;
    } else if (treebin === "b") {
      if (lastWasA) {
        return true;
      } else {
        lastWasA = false;
        return false;
      }
    } else {
      lastWasA = false;
      return false;
    }
  } else { // 不是字符串,必定是内部节点:
    return ((aThenB(treebin.l))||(aThenB(treebin.r)));
  }
}

這裡包含了對全局變量lastWasA引用。在存儲傳遞風格中,一個或更多的全局變量在每次函數調用時一起傳入,而且從每次調用返回並傳入下次函數調用從而形成牽連(thread)。代碼可以寫為如下:

function aThenB(treebin, lastWasA) {
  if (typeof(treebin) === "string") {
    if (treebin === "a") {
      return {result: false, lastWasA: true};
    } else if (treebin === "b") {
      if (lastWasA) {
        return {result: true, lastWasA: false};
      }
    } else {
      return {result: false, lastWasA: false};
    }
  } else { // 不是字符串,必定是内部节点:
    var leftCall = aThenB(treebin.l, lastWasA);
    if (leftCall.result) {
      return {result: true, lastWasA: false}
    } else {
      return aThenB(treebin.r, leftCall.lastWasA);
    }
  }
}

注意現在每次調用都接受一個額外的實際參數lastWasA,還返回兩個值:平常的返回值,和一個新值來表示原先的可變變量lastWasA的狀態。

寫存儲傳遞風格的程序可能非常痛苦,但通過將狀態隔離在函數調用之中,有助於消除競爭條件,從使代碼潛在的更加可並行化。

參見

編輯

引用

編輯
  1. ^ Friedman, Daniel; Wand, Mitchell. Essentials of Programming Languages 4th. Boston, MA: MIT Press. April 2008. ISBN 978-0262062794. 
  2. ^ Krishnamurthi, Shriram. Programming Languages, Application and Interpretation Second. self-published. November 2012 [10 February 2016]. (原始內容存檔於2016-03-13).