Visto che siamo in argomento: che differenza c’è tra \DeclareRobustCommand e la sua versione asteriscata?
Che diamine! La stessa che c’è fra \newcommand e \newcommand*. Quasi.
Una macro TeX può essere dichiarata \long al momento della definizione; in tal caso è ammesso che all’interno dei suoi argomenti, al momento della chiamata, compaia il token \par. Le definizioni con \newcommand sono tutte di macro \long, quelle con \newcommand* no.
Analogamente per \DeclareRobustCommand. Con una differenza un po’ sottile. Con \DeclareRobustCommand\pippo{…} e con la versione * si definisce un comando \pippo che non è \long e che non ha argomenti. “Ma come?”, dirai, “Posso ben scrivere \DeclareRobustCommand\pippo[4]{…} e usare i parametri nella definizione.”
Il fatto è che \DeclareRobustCommand definisce sempre due comandi; nel nostro caso “\pippo” e “\pippo “; noterai che nella seconda ho aggiunto uno spazio: proprio così, la seconda macro definita ha uno spazio nel nome e questa è la macro che può essere \long e avere argomenti.
L’espansione di primo livello di “\pippo” è proprio “\protect\pippo “. Quando LaTeX scrive sui file ausiliari, il significato di \protect è \noexpand, quindi la macro che segue non viene espansa. Quando invece i file ausiliari vengono letti, il significato di \protect è \relax, cosicché l’espansione di “\pippo” (senza lo spazio) viene eseguita completamente.
Ricapitoliamo: quando LaTeX incontra “\pippo” nell’argomento di un comando \write, lo espande in “\protect\pippo ” e lo scrive, perché l’espansione è ormai inibita. Quando legge, vede scritto “\protect\pippo” e ignora gli spazi seguenti (ormai quello spazio aggiunto durante la scrittura non fa più parte del nome, perché il file ritorna nel meccanismo di lettura così com’è), ma siccome \protect equivale a \relax, LaTeX espande “\pippo” in “\protect\pippo ” (con lo spazio che stavolta fa parte del nome) ed espande “\pippo ” andando in cerca di eventuali argomenti. I due \protect che valgono \relax sono passati intatti all’interno di TeX, ma tanto non fanno niente.
Complicato? Un po’, è vero. Come si fa a definire una macro che ha uno spazio nel nome? Con \csname…\endcsname, naturalmente.
Puoi vedere il meccanismo in azione lanciando una sessione interattiva di LaTeX dal terminale; indico con $ il prompt della shell e con * il prompt di LaTeX (il primo è sempre **)
`$ latex
**\relax
*\DeclareRobustCommand{\pippo}{A}
*\show\pippo`
La risposta sarà
`> \pippo=macro:
->\protect \pippo .`
e ci sono due spazi dopo \pippo: uno è quello del nome, l’altro quello che TeX aggiunge sempre, in questi casi, al nome del comando.
L’estensione e-TeX prevede un altro prefisso da dare alle macro, oltre ai classici \long, \outer e \global: \protected. Una macro definita (con \def) dando il prefisso \protected non viene espansa quando TeX scrive sui file ausiliari. Questo renderebbe superfluo il ricorso a \DeclareRobustCommand.
Ciao
Enrico