How to declare "newcommand" value as a sum of some number (with units) and another command so that it can be used in coordinate arithmetic?

What was originally used in the question, namely

\newcommand{\FMARGIN}{10mm+\FWIDTH}

stores as \FMARGIN the tokens in the command. Substitution and evaluation is not made until it is used. However, when TeX is looking for a length, something like 10mm+2mm will not do. Rather, the command \dimexpr10mm+2mm\relax is needed to perform the addition of lengths and provide the result as a single length which can be used by the macro seeking a length input.

\dimexpr stands for "dimensional expression" (the dimension being length) and \relax terminates the evaluation of a dimensional expression.

If one needs the result in textual form, that is, the tokens that are equivalent to a length of 12mm, then one uses \the\dimexpr10mm+2mm\relax, whereas without the \the, the result is stored as an internal length and not a series of alphanumeric tokens.

A good way to see what is happening is comparing this code:

\edef\tmp{10mm+\FWIDTH}
\detokenize\expandafter{\tmp}

to this code

\edef\tmp{\the\dimexpr10mm+\FWIDTH\relax}
\detokenize\expandafter{\tmp}

The former evaluates to 10mm+2mm while the latter evaluates to 34.14328pt. Here is the MWE.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary
    {%
        calc,
        shapes.geometric
    }
\newcommand{\FWIDTH}{2mm}
\newcommand{\FMARGIN}{\dimexpr10mm+\FWIDTH\relax}
\begin{document}
    \begin{tikzpicture}
        \path node
            [%
                isosceles triangle,
                draw=blue,
                minimum width=30mm,
                line width=1mm
            ]   {};
        \path
            [%
                draw=red,
                line width=1mm
            ]
            ($(current bounding box.north west)+(-\FMARGIN,\FMARGIN)$)
            rectangle
            ($(current bounding box.south east)+(\FMARGIN,-\FMARGIN)$);
    \end{tikzpicture}
\end{document}

enter image description here


When defining macros (such as with \newcommand), TeX does no arithmetic: you can think of it as simple substitution of strings (or to be more precise, tokens). So when you write:

\newcommand{\FWIDTH}{2mm}
\newcommand{\FMARGIN}{10mm+\FWIDTH}

no arithmetic happens in 10mm+\FWIDTH. The result is that \FMARGIN gets defined as a macro which expands to 10mm+\FWIDTH (and this has no special arithmetical meaning; it's simply a sequence of five tokens 1, 0, m, m, +, followed by the token \FWIDTH). And when you use it somewhere as \FMARGIN, under typical circumstances it will (ultimately) expand to the string 10mm+2mm, which again is simply a sequence of 8 characters: it's as if you had typed 10mm+2mm at that place.

So when you use:

        ($(current bounding box.north west)+(-\FMARGIN,\FMARGIN)$)
        rectangle
        ($(current bounding box.south east)+(\FMARGIN,-\FMARGIN)$);

it's as if you had typed

        ($(current bounding box.north west)+(-10mm+2mm,10mm+2mm)$)
        rectangle
        ($(current bounding box.south east)+(10mm+2mm,-10mm+2mm)$);

and although this happens to compile, it is clearly not what you want. Macros work this way because TeX was initially designed for typesetting, and macros were supposed to be a shortcut for saving typing, not for doing computation.

You can debug this for yourself (see what has \FMARGIN been defined as) by adding \show\FMARGIN) into the file:

\newcommand{\FWIDTH}{2mm}
\newcommand{\FMARGIN}{10mm+\FWIDTH}
\show\FMARGIN

when TeX reaches that point, it will show you the expansion and wait for you to hit Return before continuing:

> \FMARGIN=\long macro:
->10mm+\FWIDTH .
l.10 \show\FMARGIN

? 

Reading this requires some training, but what the above tells you is that \FMARGIN is defined as 10mm+\FWIDTH (not as 12mm).

So how do you fix this? In this case, because mm is a dimension that TeX happens to understand (but only when it's looking for a length, not when simply defining macros and such), there are some tricks you can use:

  • you can define \FMARGIN as a length, using \setlength, as in @cfr's answer

  • you can define \FMARGIN to expand to something that will result in 12mm when TeX is looking for a length, as in @Steven's answer

  • you can implement your original intention of somehow defining \FMARGIN to expand to 12mm, though it is slightly tricky (again, see Steven's answer).


This isn't an answer, but too long for a comment. It doesn't answer the question asked, that is. It does address a potential follow-up of how to avoid the problem.

Macros expand to their replacement text. For handling dimensions, it is easiest to use dimensions/lengths. For handling integers, it is easiest to use counts/counters.

\documentclass{standalone}
\usepackage{tikz,calc}
\usetikzlibrary{calc,shapes.geometric}
\newlength\FMARGIN
\newlength\FWIDTH
\tikzset{%
  fwidth/.code={\setlength\FWIDTH{#1}},
  fmargin/.code={\setlength\FMARGIN{10mm+#1}},
  fwidth/.forward to=/tikz/fmargin,
  fwidth=2mm,
}
\begin{document}
\begin{tikzpicture}
  \path node [isosceles triangle, draw=blue, minimum width=30mm, line width=1mm ]   {};
  \path [draw=red, line width=1mm ] ($(current bounding box.north west)+(-\FMARGIN,\FMARGIN)$) rectangle ($(current bounding box.south east)+(\FMARGIN,-\FMARGIN)$);
\end{tikzpicture}
\begin{tikzpicture}[fwidth=20mm]
  \path node [isosceles triangle, draw=blue, minimum width=30mm, line width=1mm ]   {};
  \path [draw=red, line width=1mm ] ($(current bounding box.north west)+(-\FMARGIN,\FMARGIN)$) rectangle ($(current bounding box.south east)+(\FMARGIN,-\FMARGIN)$);
\end{tikzpicture}
\end{document}

variable margins