1
$\begingroup$

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]] 
$\endgroup$
  • 5
    $\begingroup$ Evaluating CompoundExpression throws away all its arguments except the last. $\endgroup$ – John Doty May 30 '18 at 18:14
  • 1
    $\begingroup$ 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? $\endgroup$ – MarcoB May 30 '18 at 19:09
  • $\begingroup$ 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"] ] $\endgroup$ – Jason B. May 30 '18 at 19:38
2
$\begingroup$

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

" *)
$\endgroup$
2
$\begingroup$

@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:

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

x^2 + 1 + 1

For your question, then, we could do:

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

Import["MyModule"]; expressionThatIsGenerated

$\endgroup$
1
$\begingroup$

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]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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