9

I want to use @ifstar to define a command, whose non-star version stores a value in a variable and whose star version reads the value from the variable. I tried the following. It doesn't produce an error, but doesn't print the value either.

\def\sndname#1{\@ifstar\@sndname{\def\@sndname{#1}}}
\sndname{Hello U2}
\sndname*

I know that I can use this pattern, but is there a way to do it as a one-liner?

\def\foo{\@ifstar\@foo\@@foo}
\def\@foo#1{...}
\def\@@foo#1{...}

3 Answers3

7
\documentclass{article}
\makeatletter
\def\sndname{\@ifstar\@sndname{\def\@sndname}}
\makeatother
\begin{document}
Set it \sndname{Hello U2}and use it \sndname*.
\end{document}

The trick is, that not \sndname reads the argument but \def inside \sndname.

Schweinebacke
  • 26,336
7

You're abusing LaTeX syntax guidelines. The *-version of a command should generally have the same mandatory arguments as the standard version.

You can use an optional argument, instead:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\sndname}{o}
 {
  \IfNoValueTF{#1}
    {\tl_use:N \l_cocomore_sndname_tl}
    {\tl_set:Nn \l_cocomore_sndname_tl { #1 }}
 }
\tl_new:N \l_cocomore_sndname_tl
\ExplSyntaxOff

\begin{document}

\sndname[Hello U2]
\sndname

\end{document}

enter image description here

However, a better approach would be to use different commands for setting the variable and for using it.

egreg
  • 1,121,712
2

An addition to @egreg's answer, which I agree has a better syntax, but without xparse. The commented version is a TeX style definition of the command, and the uncommented is a LaTeX style definition. In the LaTeX definition the optional argument can only take a default value, here set to \empty, which can then be checked in the code. It should work as long as it is not loaded with \empty. The dots around the commands when used are just to check that no extra spaces are added. (Actually, the LaTeX version can probably be seen as a one-liner, but it is more readable like this:-)

\documentclass{article}
%%%% TeX style definition
% \makeatletter
% \def\sndname{\@ifnextchar[\opt@sndname\@sndnamevar}
% \def\opt@sndname[#1]{\def\@sndnamevar{#1}}
% \makeatother

%%%% LaTeX style definition
\newcommand\sndname[1][\empty]{%
  \ifx#1\empty
    \sndnamevar
  \else
    \def\sndnamevar{#1}%
  \fi}

%%%% Load with nothing (just in case \sndname is used before loaded)
\sndname[]
%%%%
\begin{document}
Load: .\sndname[Name of snd].

Print: .\sndname.

\end{document}
StefanH
  • 13,823