说我想在函数内部修改数字或其他一些原语。例如,如下所示(注意:伪代码):
// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, result):
if (tree == undefined) return
treeReduce(tree.left, fn, result)
result = fn(result, tree.value)
treeReduce(tree.right, fn, result)
sum = 0
treeReduce(myTree, +, sum)
显然这是行不通的,因为result
仅被重新分配,而传入的sum
将看不到修改。因此,我解决此问题的通用方法(在任何传递值的语言(如Python或Javascript)中都使用包装器:
// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, result):
if (tree == undefined) return
treeReduce(tree.left, fn, result)
result[0] = fn(result[0], tree.value)
treeReduce(tree.right, fn, result)
sumWrapper = [0]
treeReduce(myTree, +, sumWrapper)
但是,我最近在互联网上搜索了这是否是一种常见模式,并且找不到太多有关此模式的信息。具体来说,我想知道三件事:
答案 0 :(得分:2)
可以像这样完成 ,但是它会增加"sideeffects"的功能,大多数编码人员建议尽量减少这些功能。相反,您可以为其使用函数的 return 值。然后,您的代码仍将传递“ previous”(或“ start”)值作为原始值,但返回结果。
这是它在JS中的外观(我花了一些平凡的fn
来演示它执行了有序执行):
// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, start) {
if (tree === undefined) return start
let result = treeReduce(tree.left, fn, start)
result = fn(result, tree.value)
result = treeReduce(tree.right, fn, result)
return result
}
let myTree = { value: 1, left: { value: 2 }, right: { value: 3 } }
let result = treeReduce(myTree, (a,b) => a*a+b, 0)
console.log(result)
请注意,以上内容现在可以写得更简洁:
// apply fn to every value in a tree, in-order traversal
function treeReduce (tree, fn, start) {
return !tree ? start
: treeReduce(tree.right, fn, fn(treeReduce(tree.left, fn, start), tree.value))
}
let myTree = { value: 1, left: { value: 2 }, right: { value: 3 } }
let result = treeReduce(myTree, (a,b) => a*a+b, 0)
console.log(result)
在Python中:
import collections
Tree = collections.namedtuple('Tree', ['value', 'left', 'right'])
# apply fn to every value in a tree, in-order traversal
def treeReduce (tree, fn, start):
return start if not tree else (
treeReduce(tree.right, fn, fn(treeReduce(tree.left, fn, start), tree.value))
)
myTree = Tree(1, Tree(2,None,None), Tree(3,None,None))
result = treeReduce(myTree, lambda a,b: a*a+b, 0)
print(result)
JS和Python都允许将其扩展到需要设置多个原始值的情况:函数可以返回数组/列表/元组/对象,然后可以通过将它们解压缩/分解为单独的变量来进行赋值。