Any way to bundle some variables in an OOP-like object in LaTeX?

PGF has an object-oriented engine, that supports - according to the manual

classes, methods, constructors, attributes, objects, object identities, inheritance and overloading.

Here's what it looks like:

\pgfooclass{stamp}{
    % This is the class stamp
    \method stamp() { % The constructor
    }
    \method apply(#1,#2) { % Causes the stamp to be shown at coordinate (#1,#2)
        % Draw the stamp:
        \node [rotate=20,font=\huge] at (#1,#2) {Passed};
    }
}
\pgfoonew \mystamp=new stamp()
\begin{tikzpicture}
    \mystamp.apply(1,2)
    \mystamp.apply(3,4)
\end{tikzpicture}

While this is usually probably not the best way of doing things, you could just emulate the namespace of a struct by creating appropriate macro names:

\documentclass{article}

\usepackage{mwe}    % <-- only for example image
\usepackage{xparse} % <-- only for \setfigurestruct

\makeatletter
    \def\setstructfield#1#2#3{\expandafter\def\csname @struct@#1@field@#2\endcsname{#3}}
    \def\getstructfield#1#2{\csname @struct@#1@field@#2\endcsname}
    \def\ifstructhasfield#1#2{\ifcsname @struct@#1@field@#2\endcsname \expandafter\@firstoftwo\else \expandafter\@secondoftwo\fi}
\makeatother

% \setfigurestruct{name}{path}[width as fraction of \linewidth]{caption}[label]
\NewDocumentCommand\setfigurestruct{m O{.8} m m o}{%
    \setstructfield{#1}{width}{#2\linewidth}%
    \setstructfield{#1}{path}{#3}%
    \setstructfield{#1}{caption}{#4}%
    \IfValueT{#5}{%
        \setstructfield{#1}{label}{#5}%
    }%
}

% \plotfigure{figure struct name}
\newcommand*\plotfigure[1]{%
    \begin{figure}%
        \centering
        \includegraphics[width=\getstructfield{#1}{width}]{\getstructfield{#1}{path}}%
        \caption{\getstructfield{#1}{caption}}%
        \ifstructhasfield{#1}{label}{\label{\getstructfield{#1}{label}}}{}%
    \end{figure}%
}

\begin{document}

\setfigurestruct{testfig}{example-image-a}{A test image.}[fig:test]

Look at figure~\ref{fig:test}, please.

\plotfigure{testfig}

\end{document}

The output of the code above

The fields are not really stored as a structure here, but the interface acts as if they were.


A more powerful alternative would be using pgfkeys. You could write some wrapper functions emulating the "feel" of structs (similar to what I did above) if you want that, although I don't really see the sense in that.


A riskier alternative to schtandard's solution is to make delimited macros. This will*-ish* stick to the class.property syntax. We just have to define a delimited macro that expects a dot after it:

\documentclass{article}

\usepackage{graphicx}

\makeatletter
\def\newobj#1{%
  \ifcsname #1\endcsname
    \errmessage{Cannot define #1. Control sequence already defined.}
  \fi%
  \expandafter\def\csname obj@#1\endcsname{}%
  \expandafter\def\csname #1\endcsname.##1 {%
    \csname obj@#1@##1\endcsname%
  }%
}
\def\addtoobj#1#2#3{%
  \ifcsname obj@#1\endcsname\else
    \errmessage{Object #1 undefined. Use \string\newobj\{#1\}}
  \fi%
  \expandafter\edef\csname obj@#1@#2\endcsname{#3}%
}
\makeatother

\newcommand{\plotfigure}[1]{%
  \begin{figure}
    \centering
    \edef\Fw{[width=}
    \expandafter\expandafter\expandafter\includegraphics\expandafter\Fw#1.width ]{#1.url }
    \caption{#1.caption }
    \label{#1.label }
  \end{figure}
}

\begin{document}
\pagenumbering{gobble}

\newobj{Figure}
\addtoobj{Figure}{url}{example-image}
\addtoobj{Figure}{caption}{This is a figure.}
\addtoobj{Figure}{width}{0.5\linewidth}
\addtoobj{Figure}{label}{a_nice_label}

\plotfigure{\Figure}

See figure \ref{\Figure.label }

\end{document}

With this approach you create a "class" with \newobj{<name>} and add properties to it with \addtoobj{<name>}{<property>}{<value>}.

When you use, for example, \newobj{Figure}, a macro \Figure.#1␣ ( is a space) is created. This macro expands to \obj@Figure@#1. Then, when you call \addtoobj{Figure}{url}{example-image}, the macro \obj@Figure@url is defined to be example-image. Then, a call to \Figure.url␣ (notice the space!) will expand to example-image.

Be careful, whenever you use this, the \Figure macro must be followed by a ., then by a (valid) property name, then by a space. The space is part of the command!


As for your \plotfigure macro, we can use the \Figure.#1␣ without many problems, except for the optional argument to \includegraphics. The optional argument has to be expanded before the call to \includegraphics, so an \expandafter trickery is needed here. Other than that, \plotfigure{\Figure} works like a charm :)