MathGroup Archive 2010

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

Search the Archive

/. Hold -> Identity (Was: One more rules + ev<>rol problem)

  • To: mathgroup at smc.vnet.net
  • Subject: [mg114148] /. Hold -> Identity (Was: One more rules + ev<>rol problem)
  • From: kj <no.email at please.post>
  • Date: Thu, 25 Nov 2010 05:57:38 -0500 (EST)
  • References: <icg6m9$92s$1@smc.vnet.net>

In <icg6m9$92s$1 at smc.vnet.net> Bob Hanlon <hanlonr at cox.net> writes:

>Module[{map},
>  map[f, {a, b, c, d, e}] //. {
>    map[x_, {}] :> {},
>    map[x_, {y_, z___}] :> Prepend[{map[x, {z}]}, x[y]]}] // Flatten

>{f[a], f[b], f[c], f[d], f[e]}

Thanks, but note that this fails if the function f produces a list.
E.g., if f is List, then the above would yield {a, b, c, d, e},
whereas Map[List, {a, b, c,d, e}] would yield {{a}, {b}, {c}, {d},
{e}}.

In the meantime, I thought of a slight improvement on one of the
solutions I posted before; instead of 

Module[{map},
 map[f, {a, b, c, d, e}] //. {
    map[x_, {}] -> {},
    map[x_, {y_, z___}] :> Hold[Prepend][map[x, {z}], x[y]]
    } // ReleaseHold
 ]

...which is closely tailored to the details of this particular problem,
I now prefer the more general approach of wrapping the entire RHS
of the recursive rule in a Hold, and applying a single Hold ->
Identity replacement to the result of the ReplaceAll:

Module[{map},
 map[f, {a, b, c, d, e}] //. {
    map[x_, {}] -> {},
    map[x_, {y_, z___}] :> Hold[Prepend[map[x, {z}], x[y]]]
    } /. Hold -> Identity
 ]

I like this better because it can be easily turned into a programming
(meta-)rule.

In fact, this combination of a liberal use of Hold, followed by a
single /. Hold -> Identity looks to me like a pretty general strategy
for recovering the default evaluation order of expressions that
are built in stages. 

At first I thought that the way to do this was to run the final
result through ReleaseHold, but this doesn't work, because ReleaseHold
releases only one level:

Module[{map},
 map[f, {a, b, c, d, e}] //. {
    map[x_, {}] -> {},
    map[x_, {y_, z___}] :> Hold[Prepend[map[x, {z}], x[y]]]
    } // ReleaseHold
 ]

Hold[f[a], 
 Prepend[Hold[
   Prepend[Hold[Prepend[Hold[Prepend[{}, f[e]]], f[d]]], f[c]]], 
  f[b]]]

In contrast, replacing the Hold with Identity takes care of the
problem in one go, which is key.  Any solution that gets rid of
the Hold's in stages will run again into the same sort of problem
(essentially, an aberrant order of evaluation) that the Hold's were
brought in to prevent in the first place (e.g. as illustrated by
the last result:  upon release, Prepend proceeded to insert f[a]
as the first argument of the next Hold).

In fact, the more I think of it, the more I'm surprised by the fact
that Mathematica does not have (AFAIK) a built-in way to remove in
one swoop all the Hold's in an expression, irrespective of their
depth, nor mentions any way to do this in the documentation for
Hold or ReleaseHold.  Maybe there's some other standard/preferred
way of achieving the same effect.  If so, it would be good for this
to be documented more prominently, since building expressions
piecemeal, unhindered by premature evaluations, seems like a useful
thing to be able to do.

~kj


  • Prev by Date: Re: maximum of a series
  • Next by Date: Re: Plot function at specific points
  • Previous by thread: Creating Notebook containing Dynamic object with Mathkernel
  • Next by thread: Re: /. Hold -> Identity (Was: One more rules + ev<>rol problem)