- Questo topic ha 2 risposte, 2 partecipanti ed è stato aggiornato l'ultima volta 11 anni, 6 mesi fa da .
-
Topic
-
Cari amici:Vi chiedo scusa in anticipo per la lunghezza, davvero inusuale, di questo post, ma l’argomento è articolato e non semplicissimo, tanto che non sono riuscito a spiegarlo in meno parole.
Premetto anche che mi permetto di scrivere su questo tema nonostante sappia di avere solo un quadro molto parziale dello stesso, e di rischiare quindi di fare osservazioni banali, o non più attuali; ma da alcune dicussioni già intrattenute su questo forum mi sono fatto la convinzione di poter utilmente scambiare con altri un paio di informazioni circa quel poco che so sulla faccenda di cui ora parlerò. Spero che chi ne sa più di me intervenga nel dialogo, dissipando i miei dubbi e correggendo i miei eventuali errori.
L’argomento di cui intendo occuparmi è il comando “\do”, un piccolo nome per una macro poco nota ma importante usata sia nel nucleo del LaTeX, sia in classi di documento, sia in pacchetti. Vorrei che ragionassimo su quando si può usare, come si deve usare, e addirittura se sia lecito usarla (o, più precisamente, ridefinirla) al di fuori del nucleo del LaTeX. In effetti, questo intervento mi è stato ispirato da alcune osservazioni che mi sono state fatte circa il modo in cui io stesso uso la macro “\do”, ridefinendola a livello globale, in alcune classi e pacchetti di cui sono autore. A questo proposito, desidero ringraziare Claudio Beccari per avermi esortato a riflettere attentamente sulla questione: senza i suoi saggi consigli, non mi sarei reso conto di alcuni dei problemi di cui voglio ora parlare.
Data la complessità del discorso, lo suddividerò nel modo indicato dal seguente
Sommario
1. Il «problema di Dario Orsini»
2. Che cos’è la macro “\do”
3. Se e come sia lecito usare la macro “\do”
4. Come il nucleo, e alcuni pacchetti, impostano “\do”
5. Quale politica condivisa?1. Il «problema di Dario Orsini»
Per convincerci che c’è effettivamente qualcosa di cui è necessario discutere, consideriamo il seguente problema, al quale nel seguito ci riferiremo come al «problema di Dario Orsini».
Il signor Dario Orsini deve scrivere un testo nel quale ricorre molte volte il suo nome; un po’ per comodità, un po’ per cautelarsi contro eventuali errori di battitura, decide di definire un comando che lo contenga, e dato che è pigro decide di chiamare questo comando “\do” (dalle sue iniziali). Inizia dunque a scrivere:
`
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}\newcommand*{\do}{Dario Orsini}
% Controlliamo che abbia funzionato:
\show\do % visto che la definizione e` stata accettata?\begin{document}
% Ora, pero`, non funziona piu`!
Buongiorno, mi chiamo \do.
\end{document}
`
Se provate a eseguire questo codice, vedrete che la definizione di “\do” — data, notate bene, con un regolarissimo “\newcommand” — viene tranquillamente accettata: il comando diagnostico “\show”, inserito subito dopo, ce lo conferma. Eppure, subito dopo la fine del preambolo, il comando non funziona più: come mai?È già chiaro che qui c’è qualcosa che non va; ma supponiamo che il nostro amico D.O. dimentichi di mettere il punto finale alla sua frase di prova, e mandi in compilazione il codice seguente (provate anche voi):
`
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}\newcommand*{\do}{Dario Orsini}
% Controlliamo che abbia funzionato:
\show\do % visto che la definizione e` stata accettata?\begin{document}
% Ora, pero`, non funziona piu`!
Buongiorno, mi chiamo \do
\end{document}
`
Ahi: qui c’è qualcosa di importante che non va! Spero che siate d’accordo, e che ciò giustifichi questo post.2. Che cos’è la macro “\do”
“\do” è il nome riservato dal nucleo del LaTeX per indicare una macro in cui memorizzare una “azione contingente” da eseguire sugli elementi di una «\do-list». Capire cos’è “\do” coincide col capire cos’è una «\do-list»: essa è una macro senza parametri il cui replacement text è della forma
`
\do\do \do …
`
cioè una sequenza di coppie formate da un “\do” e da un token. Per capire a cosa serva ciò, guardiamo a quello che è forse l’esempio più noto di «\do-list», e cioè la lista “\dospecials”, definita fin dal plain TeX come (cfr. ltplain.dtx)
`
\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
\do\#\do\^\do\_\do\%\do\~}
`
Quando si deve comporre del testo verbatim, i caratteri «speciali» elencati in “\dospecials” devono essere interpretati come caratteri ordinari: ciò si ottiene dicendo
`
\def\do#1{\catcode`#1=12\relax}
\dospecials
`
La macro “\dospecials” esegue ripetutamente “\do” passandogli come argomento “\ “, “\\”, “\{“, … , “\~”, e ciò risulta nell’equivalente di
`
\catcode`\ =12\relax \catcode`\\=12\relax … \catcode`\~=12\relax
`
come voluto. Se avete capito questo esempio, avete capito le «\do-lists» e quindi la macro “\do”.Il concetto di «\do-list» è generale: “\dospecials” ne è solo un esempio. Per restare al solo nucleo, altri esempi sono “\verbatim@nolig@list” e “\@preamblecmds”; ma molti altri componenti (classi e pacchetti) fanno uso dello stesso concetto per scopi analoghi. La convenzione d’uso è sempre la stessa: innanzitutto si definisce la macro “\do” in modo che esegua l’azione desiderata, e immediatamente dopo si espande la «\do-list»; sarebbe ovviamente folle espandere una «\do-list» senza aver prima (ri)definito “\do”, giacché, proprio per il fatto che “\do” viene usato per una molteplicità di scopi in congiunzione con una molteplicità di «\do-lists», si eseguirebbe qualsiasi azione fosse rimasta memorizzata in “\do” dal suo precedente utilizzo.
Naturalmente sono anche possibili «\do-lists» con coppie, terne, ecc di tokens associate a ciascun “\do”, e/o con gruppi al posto dei tokens; per esempio, una «\do-list» della forma
`
\do\cmndA{} \do\cmndB{ } …
`
potrebbe essere utilmente espansa avendo preventivamente definito “\do” come
`
\def\do#1#2{\@ifdefinable#1{\def#1{#2}}}
`
Io stesso ho fatto una cosa del genere nel mio pacchetto cdpbabel, che fa parte del C.D.P. Bundle (quella mostrata qui è una sovrasemplificazione del codice):
`
\def\do#1{\addto\captionsitalian{#1}}
\do{\def\subjectname {Oggetto:}}
\do{\def\registeredname {Raccomandata}}
…
`
eccetera eccetera.3. Se e come sia lecito usare la macro “\do”
Arrivati a questo punto, la questione dell’«an», del decidere, cioè, se sia lecito oppure no ridefinire la macro “\do” al di fuori del nucleo del LaTeX dovrebbe risultare ormai pacifica: sì, se si ha bisogno di eseguire un’azione sugli elementi di una «\do-list» (magari anche solo una delle «\do-lists» del nucleo, come “\dospecials”, ma non necessariamente), non solo si può, ma anzi si deve ridefinire “\do”. La domanda che semmai ha senso porsi è quella del «come» questa ridefinizione debba essere fatta per non mandare a monte funzionalità importanti del nucleo del LaTeX, eventualità chiaramente catastrofica. Per esempio, si potrebbe sostenere che, per garantirne la sicurezza, la ridefinizione possa essere operata solo localmente, all’interno di un gruppo; ma secondo me questo punto di vista è privo di fondamento, in parte per ragioni già dette, in parte per ragioni ancora da dire.
Ripeto le già dette: poiché si sa che è usato con tante liste diverse, chi usa “\do” deve dare per scontato che esso possa contenere “pattume” residuante da un suo precedente utilizzo; in altre parole, “\do” è da considerarsi alla stregua di una «macro temporanea» («scratch macro»), un po’ come, per esempio, “\@tempa”, “\@tempb” e “\@tempc” nelle classi AMS.
C’è però ancora da dire che il nucleo del LaTeX usa “\do” anche come delimitatore di argomenti per certe macro, tipicamente aventi a che fare con le iterazioni; ma anche in questo caso ciò non comporta problemi, perché l’unica cosa che viene utilizzata di una sequenza di controllo che venga usata come delimitatore di argomenti è il suo nome (The TeXbook, pag. 203, penultima riga): quale sia la sua definizione, o assenza di definizione, corrente non ha alcuna importanza.
Esempi di ridefinizioni di “\do” al di fuori del nucleo sono abbondanti “in letteratura”, e a noi interessa qui solo parlare di qualche caso. Vi sono, innanzitutto, tutti i pacchetti che in qualche modo hanno a che fare con la composizione verbatim; ma, si dirà, gli autori di questi pacchetti sanno quel che fanno e, soprattutto, la ridefinizione di “\do” in tali esempi avviene dentro a un gruppo. Non mancano però gli esempi in cui “\do” viene ridefinito a livello globale e, come già detto, uno di questi è dato dalla classe letteracdp, di cui sono autore (è proprio per questo che sono qui a parlare della faccenda! :smile:). Supponiamo, per esempio, di voler definire una serie di macro rendendole inizialmente uguali a “\@empty”, ma di voler controllare, prima di fare ciò, che ciascuna macro che stiamo per definire non sia già definita, arrestando la compilazione con un errore in caso contrario. Un modo per fare ciò è il seguente:
`
\def\do#1{\@ifdefinable#1{\let#1=\@empty}}
\do\macroA
\do\macroB
\do\macroC
…
`
In questo caso, la «\do-list», anziché essere contenuta a sua volta in una macro, è data direttamente “in linea”. Come ripeto ancora una volta, la classe letteracdp (ma non solo essa) utilizza costrutti di questo genere, e lo fa al di fuori di qualunque gruppo, cioè a livello globale.Ora, possiamo anche essere d’accordo sul fatto che questo modo di procedere non sia molto elegante: questo non è in discussione. Ciò che è in discussione è se sia anche pericoloso, almeno potenzialmente. Ebbene, io sostengo che non lo è affatto, per tutte le ragioni qui sopra esposte. Sbaglio? Be’, bisogna considerare che ricordo perfettamente da dove, quasi vent’anni fa, imparai e copiai questa (cattiva, lo ammetto) abitudine: dalle classi AMS (amsart, amsproc, amsbook: non certo un esempio di bello stile, siamo d’accordo), le quali fanno ricorso a un trucco del genere nell’implementazione del comando “\maketitle”, per “svuotare” una serie di macro che non hanno più ragione di essere disponibili, o che addirittura devono non essere più disponibili, dopo il titolo, come “\@keywords”, “\@title”, “\title”, “\author”, o lo stesso “\maketitle”. Ecco un estratto dal codice di amsart.cls:
`
\def\@cleartopmattertags{%
\def\do##1{\let##1\relax}%
\do\maketitle \do\@maketitle \do\title \do\@xtitle \do\@title
\do\author \do\@xauthor \do\address \do\@xaddress
\do\contrib \do\contribs \do\xcontribs \do\toccontribs
\do\email \do\@xemail \do\curraddr \do\@xcurraddr
\do\commby \do\@commby
\do\dedicatory \do\@dedicatory \do\thanks \do\thankses
\do\keywords \do\@keywords \do\subjclass \do\@subjclass
}
`
Come si vede, un perfetto esempio di «\do-list» data “in linea”. Si noti che “\@cleartopmattertags” viene eseguita come parte di “\maketitle”, quindi a livello globale: in effetti, se provate a esaminare il significato di “\do” subito dopo “\maketitle”, così
`
\documentclass[a4paper]{amsart}
\usepackage[T1]{fontenc}\title{Gnus of the World}
\author{A.~U.~Thor}\begin{document}
\maketitle
\show\doGnus are big animals.
\end{document}
`
otterrete la conferma del fatto che “\do” è stato ridefinito a livello globale:
`
> \do=macro:
#1->\let #1\relax .
l.9 \show\do?
`
Sta di fatto che questo succede ancora con le classi AMS attualmente in distribuzione; quindi, se si pensa che ridefinire “\do” a livello globale rischi potenzialmente di distruggere il nucleo del LaTeX, c’è qualcuno di MOLTO più importante del sottoscritto che dovrebbe essere avvertito con estrema urgenza! 😉 (Ciò si dice non per fare dell’ironia, a questo punto perfino troppo facile, ma per spiegare — non dico giustificare — la sicumera, che a qualcuno è parsa eccessiva, di un mio precedente intervento.)Tanto mi incombeva di dire circa l’uso, o meglio, la ridefinizione di “\do” al di fuori del nucleo: è tempo ora di tornare al «problema di Dario Orsini», che è il solo vero problema rimasto aperto a questo punto, e costituisce il vero argomento di questo post.
4. Come il nucleo, e alcuni pacchetti, impostano “\do”
Perché la definizione di “\do”, che il nostro Dario Orsini dà regolarmente per mezzo di “\newcommand”, viene accettata? Molto semplicemente, perché né il nucleo del LaTeX, né la classe article (o altre classi standard) definiscono “\do”. Potete provare a invocare (pdf)LaTeX senza argomenti dalla linea di comando, e scrivere “\show\do” al prompt *: ottenete una risposta del tipo
`
This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) (preloaded format=pdflatex)
restricted \write18 enabled.
**\show\do
entering extended mode
LaTeX2e <2014/05/01>
Babel <3.9k> and hyphenation patterns for 78 languages loaded.
> \do=undefined.
<*> \show\do? x
No pages of output.
`
Possiamo verificare che la cosa è ancora vera anche dopo aver caricato article (e fontenc), compilando la seguente versione modificata del file di prova di Dario Orsini:
`
\documentclass[a4paper]{article}
\usepackage[T1]{fontenc}\show\do
\newcommand*{\do}{Dario Orsini}
% Controlliamo che abbia funzionato:
\show\do % visto che la definizione e` stata accettata?\begin{document}
% Ora, pero`, non funziona piu`!
Buongiorno, mi chiamo \do.
\end{document}
`
Tuttavia, alla fine del preambolo, durante l’esecuzione di “\begin{document}”, il nucleo del LaTeX rende “\do” uguale a “\noexpand”, con l’intenzione di prendere «a pure safety measure in case a do list is ever expanded at the wrong place», e anche perché «it will save a few tokens to get rid of the […] definition» (file ltfiles.dtx, commento precedente la linea di codice 59).Ora, a me sembra che, avendo intenzione di fare ciò, il nucleo del LaTeX dovrebbe anche impedire a Dario di definire “\do” nel preambolo, ponendolo uguale a “\noexpand” anche alla fine del nucleo (in ltfinal.dtx): immaginate lo sconcerto del povero Dario, il quale, dopo essersi visto accettare la definizione del suo comando, finito il preambolo lo trova inopinatamente trasformato in “\noexpand”, cioè in qualcosa che si comporta, per lui, in modo del tutto imperscrutabile. In effetti, si capisce ora quello che succedeva nel caso Dario dimenticasse il punto fermo al termine della frase, dopo “\do”: il compilatore s’imbatteva nella sequenza
PROTECTED15
e quindi leggeva dapprima “\noexpand\end”, equivalente a “\relax”, poi “{document}”, che aggiungeva al testo in composizione, e infine si fermava in attesa di ulteriori comandi per l’assenza di “\end{document}” alla fine del file; conseguivano panico di Dario e richiesta di aiuto a questo forum! 🙂 (In effetti, è quasi strano che, in tanti anni, non sia mai capitato…)Sembra condividere questa tesi sulla necessità di definire “\do” fin dal preambolo anche Philipp Lehman, autore del pacchetto etoolbox, il quale ultimo, fra le tante utilissime funzioni che rende disponibili, non tutte legate alle estensioni “di livello macchina” offerte da e-TeX, comprende anche degli strumenti per la gestione di «elenchi» («lists») di generici «elementi» («items»), separati da caratteri opportunamente specificati (per i dettagli, si veda [Leh2011], sezione 3.7); questi elenchi non devono avere la forma di «\do-lists» («\do-lists» sono però usate nell’implementazione), ma, in certi casi, condividono con le «\do-lists» l’idea generale di usare un (= il) comando di nome “\do” per specificare un’azione da eseguire su tutti gli elementi di un elenco dato.
L’intenzione di Lehman di riferirsi allo stesso comando (o nome di comando) “\do” utilizzato nelle «\do-lists» è evidente; egli, però, intende anche fare le cose per bene e, nel già citato manuale [Leh2011], istruisce gli utenti a (ri)definire “\do” per mezzo di “\renewcommand”; e per far sì che “\renewcommand” funzioni, al termine del pacchetto lascia “\do” impostato uguale a “\noexpand”, esattamente come il nucleo alla fine del preambolo. Si noti che, facendo così, si ottiene un comportamento che interpreta correttamente le possibili future azioni dell’utente riguardanti “\do”: un successivo
`\newcommand*{\do}[1]{…}`
chiara manifestazione di un’intenzione “alla Dario Orsini” di definire ex-novo un comando “\do”, genera un errore, mentre
`\renewcommand*{\do}[1]{…}`
che sottointende la volontà di ri-definire “quel comando “\do” di etoolbox”, viene accettato. Lasciando “\do” indefinito si ottiene invece il comportamento esattamente contrario, impedendo l’uso di “\renewcommand”, comportamento che penso anche voi, come me, giudicherete antiintuitivo.Insomma, tutto sembra indicare che lasciare “\do” indefinito nel preambolo sia sbagliato, come si era capito già dall’inizio considerando il «problema di Dario Orsini», e questa considerazione ci porta finalmente là dove volevo portarvi fin da quando ho scritto il titolo di quest’interminabile intervento, che è poi l’eterna domanda dove vanno a morire tutte le indagini teoriche insopportabilmente lunghe ed estenuanti: che fare, allora? 🙂
5. Quale politica condivisa?
Come tutti gli interventi fatti in questo forum, anche questo si propone lo scopo di chiedere un chiarimento alla comunità degli utenti LaTeX. La domanda che vi pongo è la seguente:
Supponendo di dare per assodato che
- è lecito ridefinire “\do” al di fuori del nucleo, in particolare nel codice di una classe o di un pacchetto,
- è lecito farlo a livello globale e
- è opportuno evitare di lasciare “sporco” “\do” dopo averlo così utilizzato,
quale definizione di “\do” deve essere lasciata in vigore al termine della classe o del pacchetto?
Nella lunga discussione precedente abbiamo individuato due possibili risposte a questa domanda:
- lasciare “\do” non definito
`\let \do = \@undefined`
così come fanno il nucleo del LaTeX e le classi standard; - lasciare “\do” impostato uguale a “\noexpand”
`\let \do = \noexpand`
così come fa il nucleo del LaTeX al termine del preambolo.
La prima linea di comportamento dà luogo al «problema di Dario Orsini», la seconda lo previene in modo soddisfacente.
Quando, nel 1999, scrissi la classe letteracdp, senza farmi troppe domande abbracciai convinto la prima linea di comportamento: ciò che risulta al termine di nucleo e classi standard, mi dissi, quello lascerò in vigore io. Ora mi sono reso conto che sarebbe forse meglio cambiare questa decisione. Però, un tale cambiamento avrebbe senso solo se si stabilisse, a riguardo, una politica condivisa coerentemente seguita da tutti, dove «tutti» dovrebbe comprendere anche il nucleo del LaTeX.
Come vedete, il nostro discorso ci ha portati perfino a ipotizzare una (infinitesima) modifica al file ltfinal.dtx del nucleo. Naturalmente, al giorno d’oggi modifiche di questo genere vanno soppesate con indicibile cautela, perché troppo grandi sono le montagne di codice che sono state scritte sulla base dell’assunzione che il nucleo si comporti come si comporta; tuttavia, il «problema di Dario Orsini» mi sembra degno di essere preso in considerazione.
Non so quanti avranno avuto la pazienza, e l’indulgenza, necessarie ad arrivare fino in fondo a questo interminabile post, ma desidero ringraziare chi l’avesse fatto e ancor più chi volesse rifletterci sopra e darmi una risposta.
Perdonatemi se potete, e ciao.
—
Gustavo
Testi citati
[Leh2011] Philipp Lehman, The etoolbox Package. An e-TeX Toolbox for Class and Package Authors, vers. 2.1 (January 3, 2011), visualizzabile con texdoc etoolbox.
- Devi essere connesso per rispondere a questo topic.