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: [mg109243] Re: Nest and Fold don't respect HoldFirst?
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Mon, 19 Apr 2010 02:48:22 -0400 (EDT)

Hi Arno,

My understanding is that indeed, Nest and Fold do not respect the Hold
Attributes in the way you outlined. Here is my guess for what's happening:
the behavior that you observed  is probably  just a consequence of the way
they (Nest and Fold) work (are implemented): first your function is computed
(iterated) by Nest or Fold, and then that result is copied to whatever
internal storage Nest or Fold is using to keep the intermediate result of a
given iteration. In other words, what you get as an input for the next
iteration is already a result stored in that internal storage rather than
your initial variable. And when this result is supplied to you for the next
iteration, it gets evaluated, so probably what you get is a fully evaluated
copy rather than a reference to that storage. This copy is immutable, so you
get the error when attempting to modify it. This scenario is just my
speculation, any part of it may be wrong.

Now, one of the main goals of functional style is to work on immutable
structures, so this behavior seems consistent with that ideology. Whenever
you use Hold attributes to implement pass-by-reference and in-place
modifications, you already step outside of the functional programming
paradigm. So I would not hesitate to use loops - in your situation this
seems totally appropriate.

As far as efficiency is concerned, functional programming is efficient in
Mathematica simply because it allows to work with large pieces at once,
pushing more operations into the kernel and by-passing the main evaluation
loop for many small parts of your expression. In most cases, loops are
associated with breaking expression into pieces, and that is what makes them
inefficient.  In some cases however, loops can be used to the same effect,
and then they are no less efficient than functional programming. For your
problem in particular, loops should be totally fine. In the case of lists,
you may also save a little (like 25 %) by wrapping your values in
HoldComplete rather than List, since then no UpValues lookup will take
place.

Hope this helps.

Regards,
Leonid


On Sat, Apr 17, 2010 at 3:03 AM, ap <arno.proeme 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.
>
>


  • Prev by Date: Re: piecewise function
  • Next by Date: Re: if using Mathematica to solve an algebraic problem
  • Previous by thread: Re: Nest and Fold don't respect HoldFirst?
  • Next by thread: Re: Nest and Fold don't respect HoldFirst?