# How to convert part of an expression to string?

I'm trying to generate some code. I'm trying:

ToString[CompoundExpression[Unevaluated@Import["MyModule"], expressionThatIsGenerated]]


expecting output like:

Import["MyModule"];
expressionThatIsGenerated


So, I want to output Import["MyModule"] unevaluated, but it doesn't work - Import["MyModule"] gets evaluated to expressionThatIsGenerated every time.

(Use case):

I'm going through Mathematica documentation notebooks and generating test cases (for checking compatibility of open source Mathematica implementations with original) out of them. See:

https://github.com/darvin/MMATestSuiteGenerator

After I'm finished with a notebook, my expressionThatIsGenerated looks like:

ESimpleExamples[EComment["Test if an expression is an integer:"],
ESameTest[MatchQ[12345, _Integer], True],
EComment["Test if an expression is a sum of two or more terms:"],
ESameTest[MatchQ[(x - 1)*(1 + 2*x + 3*x^2), _ + __], False]]


naturally I wanna record it into a file, with prepended Import["FileThatDefinesMyTestFrameworkFunctions"];, like that:

Import["FileThatDefinesMyTestFrameworkFunctions"];
ESimpleExamples[EComment["Test if an expression is an integer:"],
ESameTest[MatchQ[12345, _Integer], True],
EComment["Test if an expression is a sum of two or more terms:"],
ESameTest[MatchQ[(x - 1)*(1 + 2*x + 3*x^2), _ + __], False]]

• Evaluating CompoundExpression throws away all its arguments except the last. – John Doty May 30 '18 at 18:14
• It is really unclear what you are trying to achieve here. I cannot imagine a situation where this would be useful. Could you expand on the actual problem you are trying to solve with this approach? – MarcoB May 30 '18 at 19:09
• I also don't fully understand the use case, but would something like this work for you? Attributes[toString] = HoldAllComplete; toString[CompoundExpression[args__]] := With[ {strings = ToString[Unevaluated[#], InputForm] & /@ {args}}, StringRiffle[strings, ";\n"] ] – Jason B. May 30 '18 at 19:38

If exporting to a file is your only concern, why not use the "HeldExpressions" element of the "Package" Export format? This allows you to give a list of HoldComplete[…] expressions that should be exported, making it unnecessary to manually handle removal of some kind of hold wrapper.

SetDirectory@CreateDirectory[]

expr = x^2 + 1/2;

Export["test.m", {HoldComplete[Import["MyModule"];], HoldComplete@#&@expr}, "HeldExpressions"]
(* "test.m" *)

Import["test.m", "String"]
(* "(* Created with the Wolfram Language *)

Import[\"MyModule\"];

1/2 + x^2

" *)


@John gave a method using HoldForm, but this only works with single argument ToString (which uses OutputForm). Single argument ToString can do horrible things like:

ToString[x^2+1/2]

(*
1    2
- + x
2
*)


which certainly can not be reevaluated. It is better to use ToString[expr, InputForm], e.g.:

ToString[x^2+1/2, InputForm]


1/2 + x^2

However, HoldForm is not invisible when using InputForm:

ToString[HoldForm[x^2+1/2], InputForm]


HoldForm[x^2 + 1/2]

My preferred method to achieve a HoldForm-like construct within InputForm is to temporarily give the function SequenceForm a HoldAll attribute. For example:

InternalInheritedBlock[{SequenceForm},
SetAttributes[SequenceForm, HoldAll];
ToString[SequenceForm[x^2+1+1], InputForm]
]


x^2 + 1 + 1

For your question, then, we could do:

InternalInheritedBlock[{SequenceForm},
SetAttributes[SequenceForm, HoldAll];
ToString[
SequenceForm @ CompoundExpression[
Import["MyModule"],
expressionThatIsGenerated
],
InputForm
]
]


Import["MyModule"]; expressionThatIsGenerated

Unevaluated is a quote that disappears to the evaluator after its first evaluation. I think you want HoldForm, which disappears from the string representation, but otherwise persists. Then, you can inject the evaluated expression into the held expression with a replacement.

ToString[HoldForm[CompoundExpression[Import["MyModule"], etig]] /.
etig -> expressionThatIsGenerated]