# How to get Cases to wrap results in an arbitrary head?

A number of functions provide for results to be wrapped in an arbitrary head. This is very important in cases where the results should not be evaluated. Take Level as an example:

expr = Hold[{2/2, g[8/4], 1/0}];

Level[expr, {-2}, Hold]

Hold[1/2, 1/4, 1/0]


Cases however provides no such parameter, causing undesired evaluation:

Cases[expr, _Times, 3]


Power::infy: Infinite expression 1/0 encountered. >>

{1, 2, ComplexInfinity}  (* failure *)


How can this behavior be attained?

The best I have is manual RHS holding and Join, after which an arbitrary head could be Applied:

Join @@ Cases[expr, x : _Times :> Hold[x], 3]

Hold[2/2, 8/4, 1/0]


This could be done automatically as follows:

makeHeld[(L_ -> R_) | (L_ :> R_)] := L :> HoldComplete[R];
makeHeld[pat_] := x : pat :> HoldComplete[x];

heldCases[expr_, rule_, args___] :=
Join @@ Cases[Unevaluated @ expr, makeHeld @ rule, args]


I am now reasonably happy with this but I still wonder if there is a more elegant or efficient method.

For fun here is a one-line definition of makeHeld using "vanishing patterns" and Part properties:

makeHeld[(L_ -> R_) | (L_ :> R_) | L_] := x : L -> HoldComplete[R, x][[{1}]];


It's not quite as efficient and clarity suffers so I won't replace the version above with it.

• +1. I don't know why you dislike the code, it looks pretty good to me. Just one thing - I'd use Cases[Unevaluated[expr], Replace[...],args]. – Leonid Shifrin Sep 6 '13 at 6:59
• @Leonid I'm glad it looks good. I guess it just seems like a lot of code for what I think is a rather obvious omission from Cases syntax. Unevaluated[expr] does make sense regarding the name holdCases but it was my intent instead to implement this as if it was a parameter of Cases, just as it is for Level, and Cases does not have HoldFirst. – Mr.Wizard Sep 6 '13 at 7:02
• @Leonid I changed the code somewhat; I think it's easier to read and a bit more efficient. Do you agree/confirm? – Mr.Wizard Sep 6 '13 at 7:22
• @Mr.Wizard The reason I suggested Unevaluated is that otherwise the expression will evaluate, once passed to heldCases, even when you wrap it in one level of Unevaluated, because there is a rewrite step heldCases to Cases. In other words, when I need to destructure an expression while keeping it unevaluated, I use Cases[Unevaluated[expr],...], while doing the same with heldCases as heldCases[Unevaluated[expr],... won't work with your current code. Re: rewrite - quite nice, I agree. – Leonid Shifrin Sep 6 '13 at 10:49
• @rcollyer x := godObject["rcollyer", "confusticate"] -- meet me in chat ;-) – Mr.Wizard Sep 6 '13 at 12:59