1

I have a function that returns equalities, which I want to print, for example, x==y, or 2x+5==10. These usually have no meaning for mathematica, it cannot simplify it furhter.

However, sometimes the both sides are equal, but I want to be able to print the equality in unevaluated form: that is, I want Mathematica to print x==x, and not True.

A very simple example:

Print[printableEqual[x,y]]

should print x==y, while

Print[printableEqual[x,x]]

should print x==x

Edit: The reason is that I have a relation among graphs. I would like to return things like

G1 == t*G2 + s*G3

where t,s are integers, and Gi are Graphics objects in Mathematica. Just returning this works great, (Since Mathematica cannot simplify such things) EXCEPT G1 == G1 which will be True.

The trouble is that using Defer, or HoldForm gives

Private`lhs$714 == Private`rhs$714

as output, that is, the private variables in my package is not evaluated as my Graphics.

Per Alexandersson
  • 2,443
  • 1
  • 22
  • 28

4 Answers4

4

You can use Defer to do this:

In[5]:= printableEqual[x_, y_] := Defer[x == y];
In[6]:= printableEqual[1, 2]
Out[6]= 1 == 2
Sebastian Paaske Tørholm
  • 49,493
  • 11
  • 100
  • 118
3

Another trick is to just use Unevaluated:

In[1] := Print[Unevaluated[1 == 1]]
1==1
Michael Pilat
  • 6,480
  • 27
  • 30
  • 1
    @Michael Could you clarify the difference of using Defer vs. Unevaluated here? – Dr. belisarius Jan 31 '11 at 19:33
  • 1
    `Unevaluated` doesn't wrap anything around the expression. `Defer[expr]` is a wrapper that, when printed or output, displays as the unevaluated form of `expr`, but when used as input again, acts like the evaluated form of `expr`. `Unevaluated` just prevents evaluation "once", if you will. Put another way, `Head[Unevaluated[1==1]]` is `Equals`, but `Head[Defer[1==1]]` is `Defer`. – Michael Pilat Jan 31 '11 at 21:49
  • Actually, I think that `Unevaluated` does wrap the expression - it's just that the wrapping is transparent to most functions. Compare `{FullForm[Defer[1 + 1]],FullForm[Unevaluated[1 + 1]]}` and `{Head[Defer[1 + 1]], Head[Unevaluated[1 + 1]]}`. Also, see @Leonid's answer [here](http://stackoverflow.com/questions/4856177/preventing-evaluation-of-mathematica-expressions/4856721#4856721). – Simon Jan 31 '11 at 22:45
  • `Unevaluated` does wrap, but is stripped, so its invisibility is a consequence of the evaluation process. If you wrap in several layers of Unevaluated, the inner ones will remain, for example `Head[Unevaluated[Unevaluated[Print["*"]]]]`. The problem with `Unevaluated` is that you never know how many times you need to nest it, and how many of them will be stripped - this depends on a particular evaluation, can also be data-dependent, so this is not a robust way of preventing the evaluation of expression except when we do it once, and need it once. – Leonid Shifrin Jan 31 '11 at 22:58
  • 2
    @Simon: your example `FullForm[Unevaluated[1 + 1]]` is a very special case. What happens really is that this `Unevaluated` *does* get stripped during the evaluation process. But, since there are no surrounding functions (and `FullForm` is really not a surrounding function in the way it works), the result is `Plus[1,1]` (not evaluated). In such cases (when no applicable rules were found for the parts where `Unevaluated` was stripped), `Unevaluated` is restored, which is what you observed. A very similar example was given by David Wagner in his book - this is where I learned about this. – Leonid Shifrin Jan 31 '11 at 23:09
  • Sorry for the confusion, I should have said that `Unevaluated` does not result in a *persistent* wrapper around the expression. – Michael Pilat Feb 01 '11 at 00:09
  • @Michael: your formulation of "persistent wrapper" is probably the best concise way to put it that I've seen - a good image to keep in mind, thanks. – Leonid Shifrin Feb 01 '11 at 01:18
2

Usually one uses HoldForm for this sort of thing. HoldForm is a head that works like Hold, in that it doesn't evaluate its contents, but it's not displayed when it's printed as output, like so:

In[1]:= HoldForm[x == 3]
Out[1]= x == 3

In[2]:= HoldForm[x == x]
Out[2]= x == x

As with Hold, you can interpolate things into a HoldForm using With or function argument substitution, like so:

In[3]:= PrintableEqual[x_, y_] := HoldForm[x == y]

In[4]:= PrintableEqual[x, x]
Out[4]= x == x

However, this will mean that the arguments are evaluated before substitution, like so:

In[5]:= PrintableEqual[x + x, 2 x]
Out[5]= 2 x == 2x

If you don't want this to happen, you can use SetAttributes and HoldAll:

In[6]:= SetAttributes[PrintableEqual, {HoldAll}]

In[7]:= PrintableEqual[x + x, 2 x]
Out[7]= x + x == 2 x

Note that HoldForm is always there, it's just not displayed in output form:

In[8]:= PrintableEqual[x, x] // InputForm
Out[8]= HoldForm[x == x]

If you want to evaluate things, use ReleaseHold:

In[9]:= ReleaseHold@PrintableEqual[x, x]
Out[9]= True
Pillsy
  • 9,781
  • 1
  • 43
  • 70
0

Another thing you can do is to is use Grid[] to align all of your equalities - the added advantage is that since you don't actually create expressions with Equal[], you don't have to prevent their evaluation.

In[1]:= Grid[Table[{LHS[i],"\[LongEqual]",RHS[i]},{i,2}],
             Alignment -> {Right,Center,Left}]
Out[1]= LHS[1] == RHS[1]
        LHS[2] == RHS[2]

On a similar vein, you could manually typeset using

printableEqual[LHS_, RHS_] := Row[{LHS, " \[LongEqual] ", RHS}]

or more generally

printableEqual[LHS_, mid___, RHS_] := Row[Riffle[{LHS, mid, RHS}, " \[LongEqual] "]]

By the way, the output from the printableEqual[] defined above can be converted back to a real Expression using ToExpression[ToString[#]]& or something like

toRealEqual[Row[lst_List]] := Equal@@lst[[1;;-1;;2]] /; OddQ[Length[lst]] && Union[lst[[2;;-2;;2]]] == {" \[LongEqual] "}
Simon
  • 14,631
  • 4
  • 41
  • 101