Nest and Fold don't respect HoldFirst?
- To: mathgroup at smc.vnet.net
- Subject: [mg109207] Nest and Fold don't respect HoldFirst?
- From: ap <arno.proeme at gmail.com>
- Date: Sat, 17 Apr 2010 06:03:26 -0400 (EDT)
Dear group, I just wanted to check that I'm correct in thinking that I cannot use Nest or Fold to iterate a function, where that function has a HoldFirst attribute set that allows it to modify the global variable (parameter) passed to it. As a test case / example I define a function which modifies a global variable (a list) by setting the 2nd element to a random integer, and returns the modified list, as follows: SetAttributes[f,HoldFirst] f[var_] := {var[[2]] = RandomInteger[ {0,Length[var]} ], var}[[2]] Then if I simply do mylist=Range[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} I get f[mylist] {1, 8, 3, 4, 5, 6, 7, 8, 9, 10} as expected. However, if I try to Nest this function to apply it iteratively (as an alternative to a For or Do loop), as follows: Nest[f, mylist, 3] I get Set::setps: {1,2,3,4,5,6,7,8,9,10} in the part assignment is not a symbol. >> In other words, Nest seems not to respect the HoldFirst attribute of f. Instead, the list is passed by value and the resulting attempted assignment of the random integer fails. The same behaviour results from Fold if I slightly modify f to make it a function of two variables. Is this correct? And if so, is the best alternative simply to use a loop? That's easy enough, but I was just trying to be as 'functional' and hence efficient as possible, as this kind of modification of a global variable is a key step in my algorithm and needs to be as fast as possible. I have an alternative implementation where instead of trying to modify the list I Join existing parts of it with the relevant modified element, but this appears to be ~25% slower than a simple Do loop to modify the list.