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.

5

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}
  • You make expandafter sound like a disease;) – Yiannis Lazarides Mar 9 '12 at 18:44
  • @YiannisLazarides: It is ;-) This based on expl3 which is more comfortable ;-) – Marco Daniel Mar 9 '12 at 18:46
  • Expandafters and futurelets Gave me trouble for a very long time:) – Yiannis Lazarides Mar 9 '12 at 18:49
  • @YiannisLazarides: just now futurlet is mysterious for me ;-) – Marco Daniel Mar 9 '12 at 18:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.