存储传递风格

存储传递风格是一种技术,用来建模可变状态英语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).