[英]Mimicking Pass-By-Reference in Python/Javascript Using Wrappers - Good Practice?
Say I want to modify a number or some other primitive inside of a function. 假设我要在函数内部修改数字或其他原始类型。 For example, something like this (note: pseudocode):
例如,如下所示(注意:伪代码):
// 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)
obviously this won't work, because result
is just being reassigned, and the sum
passed in won't see the modifications. 显然,这是行不通的,因为只是重新分配了
result
,并且传入的sum
将看不到修改。 So a common way I have gotten around this (in any pass-by-value language like Python or Javascript) is using wrappers: 因此,我解决此问题的通用方法(在任何传递值的语言(如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)
However, I recently searched the internet to see if this is a common pattern, and can't find much information about it. 但是,我最近在互联网上搜索了这是否是一种常见模式,并且找不到太多有关此模式的信息。 Specifically, I'd like to know three things:
具体来说,我想知道三件事:
It could be done like that, however it increases "sideeffects" of your function which most coders would advise to minimise as much as possible. 可以这样做,但是会增加函数的“副作用” ,大多数编码人员建议尽量减少这些副作用 。 Instead you could use the function's return value for it.
相反,您可以为其使用函数的返回值。 Your code would then still pass the "previous" (or "start") value as a primitive, but return the result.
然后,您的代码仍将传递“ previous”(或“ start”)值作为原语,但返回结果。
Here is how it would look in JS (I took a less trivial fn
to demonstrate it performs an in-order execution): 这是在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)
Note that the above can be written more concisely now: 请注意,以上内容现在可以更简洁地编写:
// 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)
In Python: 在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)
Both JS and Python also allow to extend this to the case where you would need to set multiple primitive values: functions can return arrays/lists/tuples/objects, which can then be assigned by unpacking/destructuring them into separate variables. JS和Python都允许将其扩展到需要设置多个原始值的情况:函数可以返回数组/列表/元组/对象,然后可以通过将它们解压缩/分解为单独的变量来进行赋值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.