Chiedo preventivamente scusa, perché mi rendo conto che mi sto un po’ comportando da petulante perfettino, ma il giochetto mi ha intrigato, ci ho ripensato mentre sparecchiavo e non sono riuscito a resistere alla tentazione di finirlo, aggiungendo il trattamento degli errori:
`
\newcommand*{\newconstant}[1][]{%
\stepcounter{constant}%
\if\relax\detokenize{#1}\relax\else
\ifcsname const@\detokenize{#1}\endcsname
% emit error message: Constant already defined
\typeout{Hey!}% stub
\else
\expandafter\xdef\csname const@\detokenize{#1}\endcsname{\arabic{constant}}%
\fi
\fi
c_{\arabic{constant}}%
}
\newcommand*{\useconstant}[1]{%
c_{%
\ifcsname const@\detokenize{#1}\endcsname
\csname const@\detokenize{#1}\endcsname
\else
% emit error message (or warning?): Undefined constant
\typeout{Mmmh…}% stub
?%
\fi
}%
}
`
Ho anche pensato che se si usa \detokenize, tanto vale utilizzarlo dappertutto. Però, da seguace della chiesa ortodossa (del TeX3), mi chiedo se davvero uno voglia usare etichette come quella presentata nell’esempio seguente.
`
New
\begin{equation}
x=\newconstant
\end{equation}
New (pippo)
\begin{equation}
x=\newconstant[pippo]
\end{equation}
Use pippo
\begin{equation}
y=\useconstant{pippo}
\end{equation}
Use pippo and new
\begin{multline}
a=\useconstant{pippo}\\
+\newconstant
\end{multline}
Attempt to redefine constant
\[
h = \newconstant[pippo]
\]
Attempt to use an undefined constant
\[
g = \useconstant{pluto}
\]
Weird label
\[
f = \newconstant[p@p&ri\no\iffalse]
\]
Use it
\[
\useconstant{p@p&ri\no\iffalse}
\]
`
Io farei tutto col vecchio, “ortodosso” \@ifundefined (sì, lo so che creo una voce nella tabella di hash, ma sapete com’è, sulle questioni di religione…).Ciao.
—
GustavoP.S. Aggiungo qualche piccola modifica:
gli asterischi dopo \newcommand;
l’osservazione che la sequenza const@\detokenize{#1} potrebbe essere resa una macro, con un argomento; però, ogni bel gioco…
Ri-ciao.
Al trattamento degli errori avevo pensato anch’io, ma ero di fretta e ho preferito una soluzione “veloce”. L’uso di \detokenize per vedere se l’argomento è vuoto viene da Oberdiek, ça va sans dire. È forse il metodo più robusto, perché qualcosa che sia dentro \detokenize non può mai essere uguale a \relax, anche se uno chiamasse \newconstant[\relax]. L’uso di \@ifundefined è forse più comodo in certe situazioni, ma siccome preferisco i condizionali \ifX … \else … \fi che sono molto più flessibili per gli annidamenti, non disdegno \ifdefined o \ifcsname. Anzi! In molte situazioni non occorre definirsi un nuovo condizionale (e quindi tre comandi):
`\DeclareOption{pippo}{\let\xyz@pippo=T}
…
\ifdefined\xyz@pippo
\else
\fi`
è molto più efficiente del tradizionale
`\newif\ifxyz@pippo
%\xyz@pippofalse % default alla creazione di un condizionale
\DeclareOption{pippo}{\xyz@pippotrue}
…
\ifxyz@pippo
\else
\fi`
Un solo comando \xyz@pippo invece di tre.
Quanto alle \label strane: non hai idea di che cosa ci metta la gente. 🙂
Ciao
Enrico