# How does string interpolation work in Mathematica

I've noticed that Mathematica 8 seems to have some kind of string interpolation feature, but I couldn't find any documentation on it and I can't figure out how it works.

For example, if I enter

StringForm["x=", 1 + 2]


in a notebook and evaluate it, I get the string "x=3". If I select that cell and choose Cell->Convert To->StandardForm (Ctrl-Shift-N], Mathematica converts the cell to an expression that looks like this:

"x=\!$$1 + 2$$"


that also evaluates to "x=3"

However, if I enter the exact same character sequence on a new cell, it evaluates to "x=1 + 2".

My question is: Is this documented somewhere? How does it work?

-
If you haven't already seen it, the tutorial String-Oriented Output Formats contains some useful information. – kglr Feb 20 '12 at 10:07
@kguler would you please give me your output for: Attributes[StringForm] – Mr.Wizard Feb 20 '12 at 10:14
@Mr.Wizard, Attributes[StringForm] gives {Protected} (version 8.4). – kglr Feb 20 '12 at 10:16

StringForm does not create a string. As StringForm["x=", 1] // FullForm will show you, it stays unevaluated. But it is shown in a special way in the notebook (i.e. the  replaced by 1).

You can create a plain string from it using

ToString[ StringForm["x=", 1] ]


which will give

"x=1"


Unfortunately, when we need to build strings, this does not always work perfectly:

ToString[ StringForm["x=", 1/2] ]

1
x=-
2


This gave the result as a three-line string, in OutputForm. We can try ToString[ StringForm["x=", 1/2], InputForm ], but it'll return "StringForm[\"x=\", 1/2]" (unformatted). We can also try ToString[ StringForm["x=", 1/2], StandardForm], but the result will be a string containing box expressions (as you noticed). These special expressions can contain information about formatting (everything from font styles to two-dimensional math such as $\frac{1}{2}$), but they can only be shown in a Mathematica notebook. They are not human readable and cannot be used by other programs.

To get the desired "x=1/2", the workaround is

ToString@StringForm["x=", InputForm[1/2]]


Recap:

• StringForm does not change the expressions passed to it at all. StringForm expressions are merely displayed specially in notebooks.

• How StringForm is displayed depends on the output format set (OutputForm, StandardForm, TraditionalForm, etc.)

• Use ToString to obtain an actual string.

-
Why not simply ToString@StringForm["x=", InputForm[1/2]] ? – Mr.Wizard Feb 20 '12 at 10:18
@Mr.Wizard Fixed before I saw your comment. – Szabolcs Feb 20 '12 at 10:20

I think the key to understand what happens under the hood is that cells contain boxes which will be rendered by the frontend and sent to the kernel for evaluation. Using "Convert To" -> "StandardForm" will modify this box structure ("Cell" -> "Show Expression" or Ctrl-Shift-E to see the box structure before and after using it). Using convert to standardform on StringForm is an edge case which produces something that is probably causing more trouble than benefit, namely an InterpretationBox. This will show as one thing but evaluate as something else. You can create interesting effects with them, e.g. a string within an identification process (evaluate the cell that the following CellPrint creates):

CellPrint[
Cell[BoxData[
InterpretationBox[
"\"I am a string but would rather be a plot!\"",
Plot[x, {x, 0, 1}]
]
], "Input"]
]


I probably should add that InterpretationBox of course has many use cases where it causes more benefit than trouble and that it is nothing new but has existed at least since version 4.

-

On version 7 I get this using Show Cell Expression (Ctrl+Shift+E) on the output cell:

If you use InputForm you get:

StringForm["x=", 1 + 2] // InputForm

StringForm["x=", 3]


Which makes it clear this is a wrapper.

On your version it appears that StringForm has attribute HoldRest so that 1 + 2 is preserved in that wrapper.

As far as I know no evaluation ever takes place automatically inside a string itself, therefore entering "x = 1 + 2" by itself with any kind of trim will not result in "x = 3".

-

As mentioned before StringForm together with ToString will give the desired results.

Here are some examples, that reproduce the functionality that is provided in other languages by sprintf (or similar functions):

myStrings = {
ToString[StringForm["This is a floating point: 1\n" ,
ToString[NumberForm[5.6 10^9, NumberFormat -> (SequenceForm[#1, "e", #3] &)]]
]],

ToString[StringForm["This is a integer in blocks : 1\n" ,
ToString[NumberForm[10^9, DigitBlock -> 3]]
]],

ToString[StringForm["This is a number with funny padding : 1 " ,
ToString[NumberForm[6.888, {7, 3}, NumberPadding -> {"_", "0"}]]
]],

ToString[StringForm["This is just a string : 1 " , "FOO"]]
};
myCompleteString = StringJoin[myStrings]

FullForm[myCompleteString]

Export["text.txt", myCompleteString, "Text"]


this will give you:

This is a floating point: 5.6e9
This is a integer in blocks : 1,000,000,000
This is a number with funny padding : ____6.888 This isjust a string : FOO

"This is a floating point: 5.6e9\nThis is a integer in blocks : 1,000,000,000\nThis is a number with funny padding : ____6.888 This is just a string : FOO "


and a file text.txt with the expected output.