Which is better: a dimension or a macro?

When messing around with TikZ/PGF then I frequently find myself wanting to store a length for later use. By "length" here, I mean the word in its non-TeX meaning. As I'm doing stuff in TikZ/PGF then I tend to use \pgfmath for the later processing so it doesn't matter for usage whether I store that length as a TeX-length or as a macro (providing I remember which I've done!).

So which is the better option?

The considerations that occur to me are: number of registers of each type, speed of look-up, speed of parsing, robustness of code (I feel that for a Cargo Cult Programmer such as myself then \edef\savedlength{\oldlength} or \let\savedlength=\oldlength is safer than \savedlength=\oldlength when \oldlength might not itself be a TeX-length). But I'm sure that there are others that I haven't thought of (being a humble CCP!).

For normal LaTeX usage and few lengths in points or other fixed unit I would recommend the usage of dimension registers (LaTeX: length, TeX: \dimen). Their benefit is that they are faster, already terminated and can be prefixed with a factor. The drawback is that you need to allocate the register and must be careful not to use it on its own inside a text.

For pgfmath the benefit of the scale factor disappears almost completely because it allows you to use use * for multiplication.

One benefit for macros is that they can hold length with em or ex unit which are font size specific. If you assign such values to a length register they are converted to pt at the moment of assignment and not when they are used.

If you use mostly pgfmath expressions and need several lengths incl. font size specific ones, I would stick to macros. You will need to remember if you dealing with lengths registers or macros in several cases anyway, so it would be better to stick with one thing. \dimexpr makes this also a little simpler if you need a dimension expression.

With eTeX there is also the possibility to define pseudo-lengths using \dimexpr. You can e.g. say \def\mylength{\dimexpr 1em\relax} and use it like a length register, i.e. you can use a factor in front of it and can (and must) use \the to get the string representation. Note that pgfmath handles lengths register by detecting its type but can't handle \dimexpr yet. So \mylength will be expanded first and the \dimexpr will break. To use them in pgfmath expressions you need to convert it to a string using \the first. This is one thing which stops you from using \pgfmathsetlength as a drop-in replacement of \setlength for existing code.

• on the handling of \dimexpr in pgfmath: one possible approach would be to automatically insert *\the before any non-expandable control sequence (except \relax, I guess). This takes care of multiplication and unpacking. Of course, it breaks if the user puts a non-expandable non-register primitive in the expression. Is that an issue? – Bruno Le Floch Jun 10 '11 at 10:52
• @Bruno: IIRC the PGF code at this position was quite tricky and I couldn't hack it without studying it further. Inserting a \the or anything else might be not possible due to the way the expression is processed. But I'm not fully sure. – Martin Scharrer Jun 10 '11 at 11:20
• I don't know PGF well. But does it seem like a good approach in principle? I'm coding an expandable version of \pgfmathparse now, and that's my current plan. – Bruno Le Floch Jun 10 '11 at 13:13

In general, I would favour using TeX dimen registers for storing fixed lengths. In general, TeX is faster parsing these than the equivalent data stored in a macro. This is because registers are properly 'terminated' as far as TeX is concerned: this shows up more with other data types than for fixed lengths.

What you do need to watch is that

\let\savedlength=\oldlength


is fine when \oldlength is a macro, but when \oldlength is a dimen you are copying not the content but the pointer to a register:

\newdimen\mydimena
\newdimen\mydimenb
\mydimena 10 pt
\let\mydimenb\mydimena
\mydimena 20 pt
\showthe\mydimenb


I would use something like

\newdimen\savedlength
\savedlength\oldlength\relax


which will perform an assignment to set \savedlength to the value of \oldlength, and is safe whether \oldlength is a macro or a dimen. If e-TeX is available, I'd also use \dimexpr to avoid leaving any \relax tokens spare:

\savedlength\dimexpr\oldlength\relax


(This works because \dimexpr is terminated by a \relax which it will remove. So here the \relax will disappear to leave an whether \oldlength is a macro or a dimen.)