MathGroup Archive 2010

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Nest and Fold don't respect HoldFirst?

  • To: mathgroup at smc.vnet.net
  • Subject: [mg109230] Re: Nest and Fold don't respect HoldFirst?
  • From: Ray Koopman <koopman at sfu.ca>
  • Date: Sun, 18 Apr 2010 05:57:58 -0400 (EDT)
  • References: <hqc0vu$ftg$1@smc.vnet.net>

On Apr 17, 3:02 am, ap <arno.pro... at gmail.com> wrote:
> 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.

Use MapAt:

In[1]:= g[var_] := MapAt[Random[Integer,{0,Length@var}]&,var,2]

In[2]:= mylist = Range@10

Out[2]= {1,2,3,4,5,6,7,8,9,10}

In[3]:= g[mylist]

Out[3]= {1,9,3,4,5,6,7,8,9,10}

In[4]:= Nest[g,mylist,3]

Out[4]= {1,6,3,4,5,6,7,8,9,10}


  • Prev by Date: Re: integrate log*sinc
  • Next by Date: Re: Nest and Fold don't respect HoldFirst?
  • Previous by thread: Nest and Fold don't respect HoldFirst?
  • Next by thread: Re: Nest and Fold don't respect HoldFirst?