One problem I had with the expression-to-C converter is that CForm converts negations of terms into a negation of parenthesized terms.
For example:
In[1]:= -a b // CForm
Out[1]//CForm= -(a*b)
That looks ugly. I tried to define a new format for Times[-1, v], but this requires unprotecting Times, and led to an infinite recursion when I tried to use it. I finally found a suggestion on how to define whole new format wrappers on the comp.soft-sys.math.mathematica list, in a message posted by Carl Woll (a Wolfram employee). This is how it works:
This assignment marks CCForm (my new formatter) as a format wrapper.
In[2]:= Format[CCForm[expr_], CCForm] := expr
Note that the Out[3] text shows the new formatter name.
In[3]:= 2 + 3 // CCForm
Out[3]//CCForm= CCForm[5]
It’s showing the CCForm wrapper, though, which we don’t want to look at, so we define a top-level format for CCForm that replaces it with its argument.
In[4]:= Format[CCForm[expr_]] := expr
Now, the output looks correct.
In[5]:= 2 + 3 // CCForm
Out[5]//CCForm= 5
The case I’m trying to fix isn’t helped by this. We need to make it produce the CForm.
In[6]:= -a b // CCForm
Out[6]//CCForm= -a b
In[7]:= Format[CCForm[expr_]] := CForm[expr]
In[8]:= -a b // CCForm
Out[8]//CCForm= -(a*b)
We don’t want the result to be evaluated, so we add a HoldForm.
In[9]:= Format[CCForm[expr_]] := HoldForm[CForm[expr]]
In[10]:= -a b // CCForm
Out[10]//CCForm= -(a*b)
Now it’s in CForm, but we still have the parenthesis. I don’t understand just why this works, but making CCForm HoldAll fixes the problem.
In[11]:= SetAttributes[CCForm, HoldAll]
In[12]:= -a b // CCForm
Out[12]//CCForm= -a * b
This also prevents evaluation of the expression being formatted.
In[13]:= 2 + 3 // CCForm
Out[13]//CCForm= 2 + 3
Note that CForm does what I want if it’s made HoldAll.
In[14]:= -a b // CForm
Out[14]//CForm= -(a*b)
In[15]:= SetAttributes[CForm, HoldAll]
In[16]:= -a b // CForm
Out[16]//CForm= -a*b
Although it’s not styled as nicely as the CCForm version, and could mess up existing code, so we won’t do that.
In[17]:= ClearAttributes[CForm, HoldAll]
Now I can use CCForm instead of CForm for the output formatting of my converter, and have nicer-looking results.