# Labeling plots without evaluation

This is my first question here so please excuse my mistakes.

Let us consider a rather contrived example:

f[x_, y_, z_] := x y z
{y, z} = {1, 1};
Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> f[x, y, z]]
Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> Subscript[f, x, y, z]]
Manipulate[Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> f[x, y, z]], {y, 0, 1}, {z, 0, 1}]


Only PlotLabel is used here, but I am making the same argument for AxesLabel, Epilog -> Inset[], and other ways of labeling plots. The problem here is that the evaluator in Mathematica eagerly replaces all occurrences of f, y and z by their values, so instead of $f(x,y,z)$ in the plot one sees $x$. There are several solutions:

1. Different variables, say ff, yy and zz, can be used in the code, leaving the symbols f, y and z free for labeling. However, this makes the code much more incomprehensible.
2. Labels can be enclosed in quotes, for example, "f[x, y, z]". This works with Subscript[f, x, y, z] but the formatting is wrong for f[x, y, z] (variables are not italicized and brackets appear in lieu of parentheses).
3. Labels can be enclosed in HoldForm or Block, for example, HoldForm[f[x, y, z]] or Block[{f, x, y, z}, f[x, y, z]]. This does not work for Manipulate, presumably because it defines its own local variables.
4. Type such monstrosity as \!$$\*FormBox[SubscriptBox[\(f$$, $$x, y, z$$], TraditionalForm]\) directly in the code.

I wonder if there is a simple way to tell Mathematica to use the expression f[x,y,z] as-is, with formatting but without evaluation. It would even be better if I can tell it to, say, replace only y with its current value in Manipulate but leave z untouched.

As an additional question, it is sometimes nice to label a condition on the plot, such as $y=1$. I can get away with

Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> HoldForm[y] == y]
Clear[y]
Manipulate[
Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> Symbol["y"] == y], {y, 0,
1}, {z, 0, 1}]


but this seems awfully complicated and inconsistent. Perhaps I can again tell Mathematica to skip evaluating Equal, and treat it as a given expression?

## Edit

Based on the discussion below I have summarized several ad-hoc strategies to deal with labels:

• Define a label via

l = {HoldForm[x], HoldForm@f[x, y, z]}
l = StringForm["Plot of ", HoldForm[Subscript[f, x, y, z]]]
l = HoldForm[y == #1 \[And] z == #2] &


in global scope, before local variables creep in. These should be shielded against all global and local definitions of the variables. (The last label should be used as PlotLabel -> l[y, z].)

• Wrap Plot or Manipulate with a Module and define local labels in the same way. For example,

Module[{l = HoldForm@f[x, y, z]},
Manipulate[
Plot[f[x, y, z], {x, -1, 1}, PlotLabel -> l], {y, 0, 1}, {z, 0, 1},
Initialization :> (f[x_, y_, z_] := x y z)]]


This is okay as long as the label is defined outside of the scope in which f, y and z are actually used. But if the plotting code is to be encapsulated in a function plot[f_] := ..., then this approach fails if the label involves f and f is declared globally as a pure function, such as f = #1 #2 #3 &. In that case, one may consider plot[fn_] := ....

• If f is to be displayed unevaluated, such as $f(x,y,0.12)$, use

Manipulate[
Plot[f[x, y, z], {x, -1, 1},
PlotLabel ->
With[{y = Symbol["y"], z = z}, HoldForm@f[x, y, z]]], {y, 0,
1}, {z, 0, 1}, Initialization :> (f[x_, y_, z_] := x y z)]


y is displayed as-is, and it is wrapped in Symbol so that it is properly formatted; but y must not already be defined globally, otherwise that global value will show. z shows its current value, set probably through a Manipulate.

• If f is to be displayed in evaluated form, such as $x\times y\times0.12$, use

Manipulate[
Plot[ReleaseHold@f[x, y, z], {x, -1, 1},
PlotLabel -> With[{y = Symbol["y"], z = z}, f[x, y, z]]], {y, 0,
1}, {z, 0, 1}, Initialization :> (f[x_, y_, z_] := HoldForm[x y z])]


However, it is hard to guarantee all plotting functions are wrapped in HoldForm.

• If any of the preserved variables (x and y) are already defined globally, it is possible to guard against them with With[{x = "x", y = "y"}, ...] at the cost of x and y not being properly formatted and the risk of wrong variable ordering.

• Nothing could be done if the variable is declared in the same scope as the label is used. HoldForm[x] will display its decorated name.

In short, there is no one single solution that works in every case except global-variable injection.