2

I had understood \begin{figure} ... \end{figure} to define an environment, and that

An environment puts its content inside a TeX group, so that commands used inside the environment don’t “leak out” — the monoblock environment, above, restricts its effect to its own contents (the stuff between the \begin{monoblock} and \end{monoblock}), which is just what you need for this sort of thing.

But when I compile (pdflatex) the following:

\documentclass{article}
\usepackage{graphicx}
\usepackage{caption,subcaption}
\usepackage{comment}

\begin{document}

\begin{figure}
        \newlength{\thisFigWidth}
        \setlength{\thisFigWidth}{0.4\textwidth}
        \centering
        \begin{subfigure}{\thisFigWidth}
            \includegraphics[width=1.0\textwidth]{example-image-a}
        \end{subfigure}
        \begin{subfigure}{\thisFigWidth}
            \includegraphics[width=1.0\textwidth]{example-image-b}
        \end{subfigure}
\end{figure}

\begin{figure}
    \newlength{\thisFigWidth}
    \setlength{\thisFigWidth}{0.3\textwidth}
    \centering
    \begin{subfigure}{\thisFigWidth}
        \includegraphics[width=1.0\textwidth]{example-image-a}
    \end{subfigure}
    \begin{subfigure}{\thisFigWidth}
        \includegraphics[width=1.0\textwidth]{example-image-b}
    \end{subfigure}
\end{figure}

\end{document}

I get

! LaTeX Error: Command \thisFigWidth already defined.
               Or name \end... illegal, see p.192 of the manual.
1
  • 2
    More precisely, local definitions do not leak out, but global definitions definitely do leak out. \newlength is inherently global. Try \dimen0 through \dimen9 instead. Nov 29, 2021 at 2:13

1 Answer 1

3

Just use a single \newlength{\thisFigWidth} in the document preamble and set the length in the figure environment. According to TeX's scoping rule the setting to the register will be forgotten as soon as the environment ends.

\documentclass{article}
\usepackage{graphicx}
\usepackage{caption,subcaption}
\usepackage{comment}

\newlength{\thisFigWidth}

\begin{document}

\begin{figure}
        \setlength{\thisFigWidth}{0.4\textwidth}
        \centering
        \begin{subfigure}{\thisFigWidth}
            \includegraphics[width=1.0\textwidth]{example-image-a}
        \end{subfigure}
        \begin{subfigure}{\thisFigWidth}
            \includegraphics[width=1.0\textwidth]{example-image-b}
        \end{subfigure}
\end{figure}

\begin{figure}
    \setlength{\thisFigWidth}{0.3\textwidth}
    \centering
    \begin{subfigure}{\thisFigWidth}
        \includegraphics[width=1.0\textwidth]{example-image-a}
    \end{subfigure}
    \begin{subfigure}{\thisFigWidth}
        \includegraphics[width=1.0\textwidth]{example-image-b}
    \end{subfigure}
\end{figure}

\end{document}

You might want to provide a default value for the register based on the text width. In this case do something like

\newlength{\thisFigWidth}
\AtBeginDocument{\setlength{\thisFigWidth}{0.5\textwidth}}

Doing it at begin document ensures that the exact \textwidth is considered (in the preamble it doesn't necessarily have the final value).


Why don't \newlength instruction respect scoping rules? Because \newlength allocates a new register (there's a finite number of them) and we don't want that the same register is allocated twice, because the value stored in it would become unpredictable. Thus \newlength instructions are global. But you don't need to allocate a new register at each figure environment: just one suffices.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .