4
$\begingroup$

Let's say, we have a list:

values = {1.2, 0.04, 0.9};

Is it possible to replace 0.04 by some expression, which displays as nearly zero when printed, but evaluates still to 0.04 when inserted into another Mathematica expression? I tried

values = {1.2, Interpretation["nearly zero",0.04], 0.9};

but this does not work. Although

Print[values];

indeed gives as output

{1.2,nearly zero,0.9}

but numericalValues = 1+values evaluates to

{2.2,1+"nearly zero",1.9}

not the expected

{2.2,1.04,1.9}
$\endgroup$
1

1 Answer 1

4
$\begingroup$

You need to define how you expect this special object to interact with functions, and which functions should handle it. Based on your example I think you want the label to be stripped from the object when an operation is performed?

  • You can generally use UpSet or TagSet (or more frequently their Delayed counterparts) to provide handling rules as needed.

  • Display is most robustly handled by defining a MakeBoxes rule for your object but Format can work too.

Perhaps you only want a limited number of functions to operate on your object. Then:

MakeBoxes[note[val_, name_], form_] := ToBoxes[name, form]

note /: note[val_, name_] + x_. := val + x
note /: note[val_, name_] * x_. := val * x

Now:

values = {1.2, note[0.04, "nearly zero"], 0.9}
{1.2, "nearly zero", 0.9}
1 + values
{2.2, 1.04, 1.9}

Or if you want most functions to operate in this manner you can choose which heads "hold" your object unevaluated:

ClearAll[note]

MakeBoxes[note[val_, name_], form_] := ToBoxes[name, form]

$noteHolders = {List, foo};

note /: head_[a___, note[val_, name_], b___] := 
  head[a, val, b] /; FreeQ[$noteHolders, head]

The global variable $noteHolders is a list of Symbols that should not evaluate note when the appear as the head of an expression. It may be updated at will if you define or find new functions that need to hold note unevaluated.

Test:

values = {1.2, note[0.04, "nearly zero"], 0.9}
1 + values
{1.2, "nearly zero", 0.9}

{2.2, 1.04, 1.9}
foo[1.2, note[0.04, "nearly zero"], 0.9]
bar[1.2, note[0.04, "nearly zero"], 0.9]
foo[1.2, "nearly zero", 0.9]

bar[1.2, 0.04, 0.9]

If you want to be able copy the output "nearly zero" and use it as input you will need to create an InterpretationBox in the MakeBoxes rule; see for example:

Also however see this warning about the loss of "editability" that will result:

$\endgroup$
2
  • $\begingroup$ Such questions appear from time to time. I think it is confusing, it was for me at least, what is the purpose of Format, Interpretation, TagBox, HoldForm, UpValues etc., and what are relations between them. Those doubts are expressed and answered in many places here but what is missing is nice compact quide + short examples for real life needs. (Explanation that secific functions creates specific box is not what people need) If you or anyone else will do this I will certainly give a bounty for this. Meanwhile, +1 :) $\endgroup$
    – Kuba
    Commented Jun 23, 2015 at 13:54
  • $\begingroup$ +1. Nice collection; I tried to use Format[ nearZero[ val_] ] together with Interpretation but that does not work out as nicely. It really seems to be about "to hold or not to hold". $\endgroup$
    – gwr
    Commented Jun 23, 2015 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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