# Define function that interleaves and then evaluates its arguments

I wish to define a function interleaveWithX[statements__] with behavior such that evaluating, for example,

interleaveWithX[a, b, c, d]


produces the same results as evaluating

a; x; b; x; c; x; d


Getting the arguments interwoven is no problem; something like

interleaveWithX[statements__] := Riffle[List@statements, x]


does the job fine. But assuming that the statements and x are already defined, I'm struggling to figure out what combination of SetAttribute, Hold, Unevaluated, ReleaseHold, Evaluate, etc. I need to incorporate in my function definition, and where, in order to delay evaluation of the arguments until I've interwoven them into the desired order.

I think this does the job. Probably not in the most elegant way:

ClearAll[interleaveWithX];
SetAttributes[interleaveWithX, HoldAll];
interleaveWithX[statements__] :=
With[{list = Riffle[{Hold /@ Unevaluated[statements]}, x]},
CompoundExpression @@@ HoldComplete[list] /. Hold[y_] :> y
]

interleaveWithX[1+1, b, c, d]


HoldComplete[1 + 1; x; b; x; c; x; d]

The HoldComplete is there to show you the unevaluated output. The final function would be wrapped with ReleaseHold:

ClearAll[interleaveWithX];
SetAttributes[interleaveWithX, HoldAll];
interleaveWithX[statements__] :=
ReleaseHold @ With[{list = Riffle[{Hold /@ Unevaluated[statements]}, x]},
CompoundExpression @@@ HoldComplete[list] /. Hold[y_] :> y
]

• I had to use Hold @ x instead of x since I also want x to remain unevaluated prior to riffling, but other than that this does the job! Apart from the evaluation stuff, CompoundExpression is very helpful to know about, thanks! – thecommexokid Apr 3 '20 at 22:03