Nested \newcommand and \renewcommand

TeX does not have variables per se like other programming languages. There are special-purpose registers for holding things like counts (integers), dimensions, input and output streams, token lists, etc. but for the most part everything is defined in terms of macros. That means, to save information in a variable, one defines a macro instead.

What was done here is non-idiomatic and limited in that now the \skills command has changed its meaning irrevocably and the naïve user of the class will discover unexpected results should she use \skills twice. Normally, rather than redefining the command, one would have instead done something like this:

\newcommand\skills[1]{
    \def\@skills{
        \begin{tikzpicture}
            \foreach [count=\i] \x/\y in {#1}{
                \draw[fill=maingray,maingray] (0,\i) rectangle (6,\i+0.4);
                \draw[fill=white,mainblue](0,\i) rectangle (\y,\i+0.4);
                \node [above right] at (0,\i+0.4) {\x};
            }
        \end{tikzpicture}
    }
}

which would store the value in \@skills for later usage (in this document class, the later usage comes in the the \makeprofile command definition.

A more idiomatic thing, in fact would have been to do

\newcommand\skills[1]{\def\@skills{#1}}

and then to move the whole tikzpicture environment to the \makeprofile definition.


Defining \skills this way has the effect that at the first usage, it needs an argument. Then skills is redefined to store this value (plus some processing) such that from now on, the command (without argument) reproduces what it was set up for at the first call.

As an example, take the definition

\newcommand\myname[1]{\renewcommand\myname{#1}}

When you execute

\myname{Stefano} % corresponds to \renewcommand\myname{Stefano}

then \myname will stand for Stefano from this moment onwards, i.e., each usage of \myname will typeset Stefano.


The command \makeprofile is defined as

\newcommand{\makeprofile}{
    \begin{tikzpicture}[remember picture,overlay]
        \node [rectangle, fill=sidecolor, anchor=north, minimum width=9cm, minimum height=\paperheight+1cm] (box) at (-5cm,0.5cm){};
    \end{tikzpicture}

    %------------------------------------------------

    \begin{textblock}{6}(0.5, 0.2)
[...irrelevant code...]
        \profilesection{Skills}

        \skills
        \skillstext
        \scriptsize
        %(*)[The skill scale is from 0 (Fundamental Awareness) to 6 (Expert).]
            
        %------------------------------------------------
            
    \end{textblock}
}

and you're supposed to say \skills{x,y,z} before doing \makeprofile.

I don't find it good programming, because this cannot check for mistakes.

It would be better to do

\newcommand{\skills}[1]{%
  \def\twentysecondscv@skills{...#1...}%
}

and in \makeprofile, instead of calling \skills, do

\ifdefined\twentysecondscv@skills
  \twentysecondscv@skills
\else
  \ClassError{twentysecondscv}
    {No \protect\skills found}
    {You need to define \protect\skills before doing \protect\makeprofile}%
\fi

With this code, the error message would refer to exactly what's gone wrong.

Also \skillstext seems to be nowhere used in the provided templates. If one forgets \skills then the call in \makeprofile will just swallow \skillstext. If no \skilltext command appears, it will gobble \scriptsize, which seems there just for the purpose of being swallowed or being completely ignored.

Even better

\newcommand{\skills}[1]{%
  \def\twentysecondscv@skills{...#1...}%
  \renewcommand{\skills}[1]{\twentysecondscv@repeat{\skills}}%
}
\newcommand{\twentysecondscv@repeat}[1]{%
  \ClassError{twentysecondscv}
    {Multiple \protect#1 ignored}
    {You should have just one \protect#1 command}%
}

where \twentisecondscv@repeat can be used also for other commands that are supposed to be issued only once.

Tags:

Macros