/. 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