8

I want to define macros within a personal package for a few variables (I don't even know if I should be calling them "variables") that may or may not be defined by the user. My approach so far is this:

\newcommand\@varname{}
\newcommand\varname[1]{\renewcommand\@varname{#1}}
\newcommand\printvarname{%
  \ifthenelse{\equal{\@varname}{}}{}{\@varname}}

The first command defines an empty \@<varname>; the second command provides a user level \<varname> that set \@<varname> to the value determined by the user; and the third command checks if \@<varname> is been defined by the user, and if so, prints it.

Since I have a lot of those "variables" to set, can I have a \NewResettableCommand{<varname>} (whose argument probably need to be set without the \) that does all of the above?

BTW: I used \newcommand (instead of \providecommand) because I'm running tests in a .tex file before create the packages.

0

2 Answers 2

6

This is it:

\newcommand{\NewResettableCommand}[1]{%
  \expandafter\newcommand\csname @#1\endcsname{}
  \expandafter\newcommand\csname #1\endcsname[1]{%
    \expandafter\renewcommand\csname @#1\endcsname{##1}}
  \expandafter\newcommand\csname print#1\endcsname{%
    \ifthenelse{\equal{\csname @#1\endcsname}{}}{}{\csname @#1\endcsname}}
}

\NewResettableCommand{varname}

Just do all the same operations with #1 in place of the name.

However, it's unclear why the "emptyness" test: if the contents is empty, expanding \@varname will do nothing the same.

However, using \renewcommand for redefining \@varname is just too much: you want to redefine it, so you don't care if it's already defined or not:

\makeatletter % not when the code is in a package
\newcommand{\NewResettableCommand}[1]{%
  \expandafter\newcommand\csname #1\endcsname[1]{\@namedef{@#1}{##1}}
  \@namedef{@#1}{}
  \expandafter\newcommand\csname print#1\endcsname{%
    \ifthenelse{\equal{\csname @#1\endcsname}{}}{}{\csname @#1\endcsname}}
}
\makeatother % not when the code is in a package

The compulsory LaTeX3 version:

\RequirePackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\NewResettableCommand}{ m }
  {
   \tl_new:c { l_nrc_#1_tl }
   \cs_new:cpn { #1 } ##1 { \tl_set:cn { l_nrc_#1_tl } { ##1 } }
   \cs_new:cpn { print #1 }
     {
      \tl_if_empty:cF { l_nrc_#1_tl } { \tl_use:c { l_nrc_#1_tl } }
     }
  }
\ExplSyntaxOff

Note that here nrc is just an arbitrary prefix that you can change at will (maybe uniformizing it to the prefix you're using for your package).

4

You can use the benefits of the package etoolbox to avoid handling with expandafter:

\documentclass{article}
\usepackage{etoolbox}
\newrobustcmd*\NewResettableCommand[1]{%
 \ifcsundef{#1}
  {%
    \csdef{#1}##1{\csdef{@#1}{##1}}%
    \csdef{print#1}{%
       \ifcsempty{@#1}%
         {\typeout{****#1 is empty****}}%
         {\csuse{@#1}}%
     }%
  }   
  {\typeout{****#1 is defined****}}%
}
\makeatother

\begin{document}
\NewResettableCommand{varname}

\varname{henrique}\printvarname

\varname{}\printvarname
\end{document}
4
  • You make expandafter sound like a disease;) Mar 9, 2012 at 18:44
  • @YiannisLazarides: It is ;-) This based on expl3 which is more comfortable ;-) Mar 9, 2012 at 18:46
  • Expandafters and futurelets Gave me trouble for a very long time:) Mar 9, 2012 at 18:49
  • @YiannisLazarides: just now futurlet is mysterious for me ;-) Mar 9, 2012 at 18:52

You must log in to answer this question.

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