Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Consider the following toy example:

Hold[{1, 2, x}] /. x -> Sequence[3, 4]

It will give

Hold[{1, 2, Sequence[3, 4]}]

because Sequence[] (like Unevaluated) is expanded only in the first level of heads with attribute HoldAll.

How can I obtain Hold[{1,2,3,4}]? What is the simplest way to do this?


  • Use case: I am trying to generate a piece of code that will be passed to Compile. I need to inject a variable number of iterators (which I have as a list) into a Do expression:

    Hold[Do[code, iterators]] /. iterators -> Sequence[{i,5}, {j,5}]
  • I would prefers solutions that don't match on the expression enclosing x. I would not like to repeat this expression (a Do in this case) in my code.

  • It's perhaps worth pointing out that

    Hold[{1, 2, f[3, 4]}] //. f[x___] :> x


    Hold[{1, 2, Sequence[3, 4]}]

    so I can't easily implement a manual sequence-flattening step.


Based on Leonid's code we can write a flattenSequence[] function that will flatten out all Sequence expressions at any level:

flattenSequence[expr_] := 
 expr //. f_[left___, Verbatim[Sequence][middle___], right___] :> 
   f[left, middle, right]

flattenSequence[Hold[{1, Sequence[2, 3]}]]

(* ==> Hold[{1, 2, 3}] *)

Based on Mr.Wizard's code we can write a general function for injecting subexpressions into other expressions while supporting Sequence:

ClearAll[inject1, inject]

SetAttributes[inject1, HoldFirst]
 inject1[expr_, (Rule|RuleDelayed)[var_Symbol, values : Verbatim[Sequence][__]]] :=
  Replace[Unevaluated[values], Sequence[var__] :> expr];
 inject1[expr_, (Rule|RuleDelayed)[var_Symbol, value_]] :=
  Replace[Unevaluated[value], var_ :> expr],


SetAttributes[inject, HoldAll]
inject[rules_, expr_] :=
  {Rule, RuleDelayed},
  SetAttributes[{Rule, RuleDelayed}, HoldFirst];
  ReleaseHold@Fold[inject1, HoldComplete[expr], rules]


inject[{a -> Sequence[b, 3], b :> 1 + 1}, Hold[{a, b}]]

(* ==> Hold[{1 + 1, 3, 1 + 1}] *)

The replacements are done one after the other, so the second one can use the result of the first. Rule and RuleDelayed are both handled correctly.

share|improve this question
If you don't insist on Sequence it might be easier – acl Feb 17 '12 at 18:43
If you can solve this in a direct and robust way I think it will call into question the need for Sequence at all. – Mr.Wizard Feb 17 '12 at 19:22
I just read this. You have plenty of answers already. I just wanted to point out that those answers that rely on building the expression on the rhs of a rule, such as the firsts of MrWizard, respect scoping so you can get things renamed if you are injecting inside a scoping construct. This means that your inject might too. Try inject[{aa -> {3, xx}}, Hold@With[{xx = 8}, Hold[{1, 2, aa}]]] – Rojo Jul 17 '12 at 13:49

10 Answers 10

up vote 48 down vote accepted
{3, 4} /. {x__} :> Hold[{1, 2, x}]
Hold[{1, 2, 3, 4}]

Leonid Shifrin used this here long before I wrote this answer.

In light of Leonid's comment to halirutan it is worth pointing out that you can inject expressions from an arbitrary head including Hold. You can also use -> rather than :> like this:

expr = Hold[{1, 2, x}];

Hold[6/2, 2 + 2] /. _[x__] -> expr 
Hold[{1, 2, 6/2, 2 + 2}]
share|improve this answer
very cool actually – acl Feb 17 '12 at 20:30
@acl I lied though: it still uses Sequence, just in the form of BlankSequence. halirutan uses SlotSequence. So I think it is not possible without Sequence of one brand or another. – Mr.Wizard Feb 17 '12 at 20:32
Yes, but that's beyond the point. One could also do all this by converting to strings and replacing, and to me the other answers seem almost as clumsy as that. You do it with a much lighter touch. – acl Feb 17 '12 at 20:36
@Kuba This is not an injection but rather a replacement so it is not quite the same as this question. I think Leonid's method is probably the most applicable, e.g. If[Hold[{a, b}], If[Hold[{c, d}], e]] //. h_[x___, _[{y___}], z___] :> h[x, y, z]. The //. is not efficient on long expressions but handling that will make this longer, making other methods comparatively more attractive. – Mr.Wizard Mar 6 '15 at 5:57
@Mr.Wizard Good point. Thanks anyway :) Let me delete those comments then. – Kuba Mar 6 '15 at 6:00

How about this:

SetAttributes[inject, HoldRest];
inject[Hold[{args__}], new__] := Hold[{args, new}]

This will also accept Sequence[3,4] as a second argument. Sequences are spliced, while arguments themselves not evaluated.


You can also use a composite rule, with some head s instead of Sequence (you can localize s if needed):

Hold[{1, 2, x}] /. x -> s[3, 4] /. 
  f_[left___, s[middle___], right___] :> f[left, middle, right]
share|improve this answer
This is exactly what I meant when I said "I would prefers solutions that don't match on the expression enclosing x. I would not like to repeat this expression (a Do in this case) in my code." This will be ugly with the Do. – Szabolcs Feb 17 '12 at 19:58
@Szabolcs Does my update address you needs? You could also wrap s around your Sequence, if you naturally get your results as a Sequence – Leonid Shifrin Feb 17 '12 at 20:07
Yes, it does. This can be expanded into a function that will flatten out all Sequence elements in an arbitrary held expression (i.e. it can made into a self-contained and general tool that integrates well with other solutions) – Szabolcs Feb 17 '12 at 21:08

One way is to use Function and the possibility of SlotSequence. I define an additional function f to be sure nothing gets evaluated:

f[x_] := Print["Evaluated"];
Function[Hold[Do[f[1], ##]]][{i, 5}, {j, 5}]

  Hold[Do[f[1], {i, 5}, {j, 5}]]
share|improve this answer
This will have a problem when i or j have values before evaluation. You can use Function[Null,Hold[Do[f[1],##]],HoldAll] to avoid it. – Leonid Shifrin Feb 17 '12 at 19:59

Not sure how robust this is, but you could do something like

flattenSequence[expr_, {x_, p__}] := Module[{f, t},
  f[t__] = expr /. x -> t;

Then for the example above

flattenSequence[Hold[{1, 2, x}], {x, 3, 4}]
Hold[{1, 2, 3, 4}]
share|improve this answer

Neat solutions provided, but there are probably more straight forward ways to solve the original problem. One of these might help.

In:= s=0; Apply[Do[s+=i^i,{i,##}]&,Hold[1,12,3]]; s  

Out[75]= 10000823800  

In:= r=Hold[s=0;{1,12,3};s];  
Part[r,1,2,0]=(Do[s+=i^i,{i,##}]&); ReleaseHold[r]  

Out= 10000823800  
share|improve this answer

I remarked before that I didn't think this was possible without Sequence, SlotSequence, BlankSequence, etc. (Without using string processing or the like that is.) It seems I was wrong, unless there is an implicit Sequence in here:

Hold[1 + 1, 2 + 2, #] & @ Unevaluated[3 + 3, 4 + 4]
Hold[1 + 1, 2 + 2, 3 + 3, 4 + 4]
share|improve this answer
This works fine because you are injecting at first level inside Hold. See my following answer for clarifications. – Federico Mar 22 '13 at 23:05
Indeed, there is an implicit Sequence: try {#}&@Unevaluated[1, 2] // Trace. – Federico Aug 4 '15 at 17:22
@Federico I have this vague memory that I saw that in the trace when I posted this but that I did not consider it a "real" Sequence since it appears later? I don't know, and I haven't given this a lot of thought since then. Anyway, thanks for noting that for future readers. – Mr.Wizard Aug 5 '15 at 5:04

Perhaps something like this?

replaceFlatteningSequences[lhs_, pat_ :> rhs_] /; MatchQ[lhs, pat] := 
 lhs /. lhs -> rhs
replaceFlatteningSequences[lhs_, pat_ :> Sequence[repSeq__]] := 
  lhs /. {Slot -> tag, SlotSequence -> tag["Sequence"], 
        Function -> tag["Function"]} /. pat :> ## /. 
     all_ :> (all &[repSeq]) /. {tag["Function"] -> Function, 
     tag["Sequence"] -> SlotSequence} /. tag -> Slot

To be used

replaceFlatteningSequences[Hold@With[{x = 8}, ## aa &], 
 aa :> Sequence[x, 4]]

Hold[With[{x = 8}, ##1 x 4 &]]

share|improve this answer

In a previous answer Mr.Wizard suggested

Hold[1 + 1, 2 + 2, #] &@Unevaluated[3 + 3, 4 + 4]

However injecting deeper inside a Hold with this technique does not work:

Hold[{1 + 1, 2 + 2, #}] &@Unevaluated[3 + 3, 4 + 4]

returns Hold[{1 + 1, 2 + 2, Sequence[3 + 3, 4 + 4]}].

I would like to point out that a little variation does indeed work:

Hold[{1 + 1, 2 + 2, ##}] &[3 + 3, 4 + 4]

And if one does indeed want the arguments not to be evaluated, then it is possible to use

Function[Null, Hold[{1 + 1, 2 + 2, SlotSequence[1]}], {HoldAll}][3 + 3, 4 + 4]
share|improve this answer

I though it is nice untill I had to add reparse function :)

SetAttributes[mySequence, HoldAllComplete];
mySequence[args__] := RawBoxes[  MakeBoxes[{args}][[1, 2]]  ];
reparse = ToExpression @* FrontEndExecute @* FrontEnd`ReparseBoxStructurePacket @* ToBoxes

y = 7;
Hold[{1, x, 2, x, 3}] /. x :> RuleCondition @ mySequence[y, 1+2] //reparse
 Hold[{1, y, 1 + 2, 2, y, 1 + 2, 3}]
share|improve this answer
But the result is not that expression, it just looks like that expression. It cannot be re-used programmatically, and the produced cell cannot even be edited manually within the front end, then evaluated, without producing errors. – Szabolcs Aug 4 '15 at 10:53
@Szabolcs good point, fixed. but it is not so clean now :( – Kuba Aug 4 '15 at 11:06

Ok. Here comes the Inactivate, Mathematica 10's powerful feature.

Inactivate could not solve injecting expression into Hold.

But you mentioned you actually want to use this to inject Do iterator in Compile. This can be done directly by Inactivate without Hold stuff. Use this

Activate[Inactivate[Compile[{}, Do[code, iterators]]] /. 
  iterators -> Sequence[{i, 5}, {j, 5}]]

I personally think that with Inactivate and Activate, we can think many things differently now, especially meta programming.

share|improve this answer
@Mr.Wizard Oh, yeah, But my second part solve Compile problem, what do you think? If this is also unnecessary, I will delete my answer : ) – matheorem Jan 14 at 15:42
No, I can see value in that part. Here's a +1. :-) – Mr.Wizard Jan 14 at 16:10

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.