Como usar @ifstar com argumentos

Como usar @ifstar com argumentos

Quero usar @ifstarpara definir um comando, cuja versão não estrela armazena um valor em uma variável e cuja versão estrela lê o valor da variável. Eu tentei o seguinte. Não produz erro, mas também não imprime o valor.

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

Eu sei que posso usar esse padrão, mas existe uma maneira de fazer isso como uma linha?

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

Responder1

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

O truque é que isso não \sndnamelê o argumento, mas \defdentro \sndname.

Responder2

Você está abusando das diretrizes de sintaxe do LaTeX. A versão * de um comando geralmente deve ter os mesmos argumentos obrigatórios que a versão padrão.

Você pode usar um argumento opcional:

\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}

insira a descrição da imagem aqui

No entanto, uma abordagem melhor seria usar comandos diferentes para definir a variável e usá-la.

Responder3

Uma adição à resposta do @egreg, que concordo que tem uma sintaxe melhor, mas sem xparse. A versão comentada é uma definição de estilo TeX do comando, e a não comentada é uma definição de estilo LaTeX. Na definição do LaTeX, o argumento opcional só pode assumir um valor padrão, aqui definido como \empty, que pode então ser verificado no código. Deve funcionar desde que não esteja carregado com arquivos \empty. Os pontos ao redor dos comandos, quando usados, servem apenas para verificar se nenhum espaço extra foi adicionado. (Na verdade, a versão LaTeX provavelmente pode ser vista como uma linha única, mas é mais legível assim:-)

\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}

informação relacionada