Operations on expressions within Hold

I want to convert {Hold[1 + 2], Hold[3 + 4], Hold[5*6]} into Hold[{1 + 2, 3 + 4, 5*6}].

I have tried

{Hold[1 + 2], Hold[3 + 4],  Hold[5*6]} /. {Hold[a_], Hold[b_], Hold[c_]} -> Hold[{a, b, c}]

Hold[{1 + 2, 3 + 4, 5 6}]


Is there a simpler way?

• Related (perhaps duplicate): Join held lists, Injecting Sequence into Hold. Oct 26, 2013 at 7:07
• It's a shame this question was closed as a duplicate. I would use: Distribute[{Hold[1 + 2], Hold[3 + 4], Hold[5*6]}, Hold]. Jun 7, 2017 at 5:41
• @CarlWoll what's the benefit of Distribute over Thread there? Jun 8, 2017 at 4:28
• @CarlWoll I must be missing something. Wouldn't your answer be equally valid to (32119)? Why reopen this one rather than answering that one? Jun 11, 2017 at 15:01
• @Mr.Wizard I wanted to discuss the step in this question in a bit more detail, that is the {__Hold} -> Hold[_List] transformation. In question 32119, this transformation can be used as one piece of an answer, but there are many answers that don't use this transformation at all. Jun 11, 2017 at 18:06

Join works with every Head so it seems to be the best way here:

Join @@ {Hold[1 + 2], Hold[3 + 4], Hold[5*6]}

Hold[1 + 2, 3 + 4, 5 6]


and if you really need those {} inside:

% /. Hold[x__] :> Hold[{x}]

Hold[{1 + 2, 3 + 4, 5 6}]


One way which works no matter how many elements your list has is to use Flatten

expr = {Hold[1 + 2], Hold[3 + 4], Hold[5*6]};
Flatten[Hold @@ expr, 1, Hold]

(* Hold[1 + 2, 3 + 4, 5 6] *)


You see that the list braces are not created. They could be reconstructed too but the question is whether you really need them. I assume for your purpose it is not really a difference whether you have List[e1,e2,...] or Hold[e1,e2,...] but Hold has the advantage of not evaluating your expression.

If you want the list, you can add another rule

expr /. {a__Hold} :> Flatten[Hold[a], 1, Hold] /.
Hold[a__] :> Hold[{a}]

(* Hold[{1 + 2, 3 + 4, 5 6}] *)


Or you define a function which basically does the same but the rules are hidden in the DownValues

f[{a__}] := f[a];
f[a__Hold] := f[Flatten[Hold[a], 1, Hold]];
f[Hold[a__]] := Hold[{a}];

f[expr]

(* Hold[{1 + 2, 3 + 4, 5 6}] *)


A couple direct ways of doing this are to use Thread and Distribute.

Thread[{Hold[1 + 2], Hold[3 + 4],  Hold[5*6]}, Hold]
Distribute[{Hold[1 + 2], Hold[3 + 4],  Hold[5*6]}, Hold]


Hold[{1 + 2, 3 + 4, 5 6}]

Hold[{1 + 2, 3 + 4, 5 6}]

The problem with Distribute is that it distributes, so if the Hold objects have more than one argument, you will get probably unwanted distribution.

Distribute[{Hold[1+2, x], Hold[3+4], Hold[5+6]}, Hold]


Hold[{1 + 2, 3 + 4, 5 + 6}, {x, 3 + 4, 5 + 6}]

On the other hand, the nice thing about Distribute is that you can stick in arbitrary heads:

SetAttributes[f, HoldAll];
Distribute[{Hold[1+2], Hold[3+4], Hold[5*6]}, Hold, List, f, g]


f[g[1 + 2, 3 + 4, 5 6]]

Just like Distribute, Thread may not work as desired when the Hold objects have more than one argument:

Thread[{Hold[1 + 2, x], Hold[3 + 4],  Hold[5*6]}, Hold]


Thread::tdlen: Objects of unequal length in {Hold[1+2,x],Hold[3+4],Hold[5 6]} cannot be combined.

{Hold[1 + 2, x], Hold[3 + 4], Hold[5 6]}

Thread[{Hold[1 + 2, x], Hold[3 + 4, y], Hold[5*6, z]}, Hold]


Hold[{1 + 2, 3 + 4, 5 6}, {x, y, z}]

Finally, Thread has support for a 3rd argument, although I don't think I've ever used it:

Thread[{Hold[1+2, x], Hold[3 + 4], Hold[5*6]}, Hold, 1]


Hold[{1 + 2, Hold[3 + 4], Hold[5 6]}, {x, Hold[3 + 4], Hold[5 6]}]

Summarizing, I find Distribute and Thread useful when working with Hold objects.

Here is an interesting way:

expr = {Hold[1 + 2], Hold[3 + 4], Hold[5*6]};
expr /. {Hold -> Sequence, List -> Hold}


Hold[1 + 2, 3 + 4, 5 6]

And if you want the inner List back:

expr /. {Hold -> Sequence, List -> Hold} /. Hold[x__] :> Hold[{x}]

Hold[{1 + 2, 3 + 4, 5 6}]