(Con le scuse per una lunga risposta che va in una direzione diversa dall'ambito del sito: francamente sono stato sorpreso di vedere la domanda qui in primo luogo ...)
TeX è stato progettato per la composizione, non per la programmazione; quindi, nella migliore delle ipotesi, è "strano" se considerato come un linguaggio di programmazione.
- Donald Knuth, tipografia digitale, pagina 235
Ho letto molto negli ultimi due anni sulla storia antica (circa 1977) di TeX e molto di ciò che Knuth ha scritto. La mia conclusione è che nel momento in cui parliamo di "TeX (come linguaggio di programmazione)" , qualcosa non va già.
Se guardiamo ai primi "documenti di progettazione" per TeX scritti prima (vedi TEXDR.AFT
e TEX.ONE
, pubblicati in Digital Typography ), è chiaro che Knuth stava progettando un sistema destinato principalmente a comporre The Art of Computer Programming (ha detto (ad esempio qui ) che gli utenti principali che aveva in mente erano se stesso e il suo segretario), con l'idea che, opportunamente modificato, potesse essere utile più in generale. Per salvare la digitazione, per le cose che uno ha dovuto fare ripetutamente (ad esempio ogni volta che TAOCP doveva includere una citazione di un autore, ti consigliamo di spostarti verticalmente di un certo importo, impostare un determinato tratto di linea, prendere un certo carattere, comporre il virgolette allineate a destra, seleziona un altro carattere, componi il nome dell'autore ...), c'erano macro.
Puoi immaginare il resto. Quello che abbiamo in TeX è un caso di "completamento accidentale di Turing" ( altro ), tranne per il fatto che è accaduto nel mezzo di una comunità (scienziati informatici e matematici, e DEK stesso deve anche "incolpare") che erano (purtroppo) troppo intelligente per ignorarlo. (La leggenda narra che Michael Spivak non aveva mai programmato prima di incontrare TeX, ma era così preso che ha finito per scrivere AMS-TeX, al momento uno dei set di macro più complicati esistenti.) Perché TeX è stato scritto per essere trasportabile su un gran numero di sistemi (che all'epoca era un grosso problema), c'era sempre la tentazione di fare tutto in TeX. Inoltre, a causa della sua esperienza nella scrittura di compilatori, Knuth ha scritto TeX come un compilatore, e occasionalmente lo ha descritto come uno, e se il programma che funziona sul tuo input è un "compilatore", allora sicuramente stai programmando, giusto?
Puoi leggere un po 'di più su come Knuth non avesse intenzione di eseguire alcuna programmazione in TeX e su come "inserisse molte delle funzionalità di programmazione di TeX solo dopo aver calciato e urlato", in questa risposta . Qualunque fossero le sue intenzioni, come ho detto, le persone hanno iniziato a capire come (ab) utilizzare il sistema macro TeX per realizzare prodigi sorprendenti di programmazione. Knuth lo ha trovato affascinante e (oltre ad aggiungere alcune funzionalità in TeX stesso) ne ha incluse alcune nell'Appendice D "Dirty Tricks" di The TeXbook, ma si scopre, nonostante il nome, che "nove esempi su dieci sono utilizzato nell'implementazione di LaTeX ”.
In altre parole: LaTeX, il sistema macro che Leslie Lamport ha scritto su TeX, come idea , è eccezionale. Creare documenti in modo semantico, strutturato e orientato all'uomo, piuttosto che (Knuth), il modo orientato alla pagina di TeX (o come lo chiamava Lamport, logico piuttosto che visivo ) è fantastico. Ma implementare qualcosa di così complicato come LaTeX usando le macro di TeX piuttosto che in un linguaggio di programmazione "corretto" è, a mio avviso e almeno se fosse stato fatto oggi, a metà strada tra un errore gigantesco e un atto di sfrenata perversità. Anche Knuth è scioccato dal fatto che le persone non si limitino a estendere il programma TeX invece di fare tutto nelle macro TeX.
Oggi ci sono modi molto migliori per fare "programmazione"; puoi usare un programma esterno in una delle molte lingue ampiamente disponibili sui computer della maggior parte delle persone, oppure puoi usare LuaTeX e programmare in Lua (e fare un lavoro migliore di quanto tu possa mai fare con le sole macro TeX, perché puoi manipolare strutture interne e algoritmi al giusto livello). E se lo fai bene, potresti avere programmi che funzionano meglio o più velocemente di quelli implementati nelle macro TeX.
Il compito di rendere più veloci i programmi in TeX è quasi divertente se visto in questa luce, e mi ricorda le ultime parole del documento che descrivono un altro "linguaggio" di programmazione "accidentalmente Turing completo": Tom Wildenhain, il delizioso " On the Turing Completeeness of MS PowerPoint ( video ) dell'anno scorso:
Mentre PPTXTM dimostra la possibilità teorica di sviluppo di PowerPoint, […]. È inoltre necessario lavorare nell'ottimizzazione delle applicazioni di PowerPoint. C'è un grande potenziale qui per sfruttare il buffering automatico di PowerPoint della diapositiva successiva, che attraverso un accurato posizionamento della diapositiva può essere utilizzato per aumentare notevolmente le prestazioni dell'applicazione.
L' aneddoto descritto da Lipton è illustrativo. Non solo non è mai esistita una semantica formale di TeX, ma è anche improbabile che ce ne sia una. È troppo "strano" un "linguaggio" per quello, e (come spero di aver spiegato sopra) non è nemmeno inteso come un linguaggio. Ad esempio, potresti pensare di scrivere macro come funzioni, ma introduce un singolo carattere randagio (anche uno spazio ) e TeX lo considera immediatamente come un'istruzione di composizione.
In breve: TeX ritorna alla composizione al più presto possibile e quando espande le macro lo fa a malincuore (impaziente di arrivare al suo "vero" lavoro di composizione), e queste espansioni possono esse stesse dipendere da centinaia di tipi di "stato" all'interno il programma TeX (i valori di parametri come \hsize
o \baselineskip
, il contenuto di caselle e altri registri ...), motivo per cui qualsiasi semantica formale di TeX deve necessariamente essere qualcosa che tenga conto dell'intero stato del programma e di tutta la sua memoria, fino a quando finiscono con qualcosa come "il significato del codice TeX è qualunque cosa faccia TeX", in una forma più complessa del programma TeX stesso.
Così bene, (se ti ho convinto) TeX non era inteso come un linguaggio di programmazione e non funziona come quelli reali, non esiste una semantica formale e ci sono modi migliori per programmare oggi - ma tutto ciò non aiuta con il tuo domanda reale / problema, e cioè che, in pratica, molti documenti significato per l'elaborazione da TeX fanno uso complicato macro (come LaTeX e TikZ), edifici mozzafiato complessità mostruosa costruito su uno sopra l'altro. Come possiamo renderlo più veloce e ideare "passaggi di ottimizzazione"?
Non ci arriverai con la semantica formale IMO. Ci ho pensato di recente e di seguito sono riportati alcuni pensieri preliminari.
La mia impressione è che Knuth fosse uno degli esperti scrittori di compilatori negli anni '60 (ecco perché gli è stato chiesto di scrivere il libro dei compilatori trasformato in The Art of Computer Programming ), e TeX è (in molti modi) scritto come erano i compilatori scritto negli anni '70, diciamo. Le tecniche e il design del compilatore sono migliorati da allora, e così può essere il programma TeX. Ecco alcune cose che possono essere fatte, accelerando le cose:
In sostanza, TeX è scritto come una "routine interpretativa", in cui gli "occhi" e la "bocca" di TeX (le sue routine di input) forniscono istruzioni al suo "stomaco" (le sue routine semantiche), da eseguire una per una. (Puoi vedere un elenco nella parte 15 del programma TeX .) Ad esempio, quando gli occhi / la bocca di TeX incontrano \hfill
o \hskip
nel suo input, lo stomaco riceve un comando "hskip", su cui agisce. Questo è simile a quello che oggi si chiamano interpreti bytecode e potrebbe esserci un valore nel refactoring del programma TeX per emettere esplicitamente questi bytecode / codici operativi, in modo che possiamo essere in grado di utilizzare le tecniche di compilazione esistenti (oggi più convenzionali). O almeno memorizzali nella cache per evitare di ripetere il lavoro. Naturalmente ci sono molte sfide:
L'esecuzione di un comando nello "stomaco" di solito comporta ancora la lettura dell'input, ovvero il lavoro delle routine di input e delle routine semantiche non avviene in fasi separate. Ad esempio il comando "hskip", se fornito \hskip
(anziché dire \hfill
) invocherà la scan_glue
lettura di una specifica di colla dall'input, che a sua volta può comportare l'espansione di macro e così via fino a quando non vengono trovati abbastanza token per la colla, lasciando lo stack di input in un stato sostanzialmente diverso.
Motori come eTeX e pdfTeX e XeTeX e LuaTeX introducono nuovi comandi e primitive (le primitive eTeX / pdfTex sono praticamente utilizzate da tutti nella pratica); dovrai supportarli anche tu, non solo quelli del programma TeX originale di Knuth.
Potremmo fare qualcosa come "esecuzione speculativa", elaborare paragrafi futuri (magari iniziando da checkpoint naturali come nuove sezioni o capitoli) in parallelo (usando più core), tenendo traccia di tutto lo stato interno di TeX che usano (dipendono) e lanciando via quel lavoro (e rifandolo) se in seguito scopriamo che un paragrafo precedente finisce per cambiare parte di quello stato. Al momento TeX funziona interamente in sequenza su 1 processore; l'hardware tipico si è spostato in una direzione diversa e sono disponibili più core.
Ancora più semplice, potremmo semplicemente memorizzare nella cache il lavoro (a quale stato TeX è stato effettuato l'accesso e modificato) da una determinata sezione del file di input. (Potremmo fare questa memorizzazione nella cache a livello dell'input - il risultato netto dell'espansione di tutte le macro - o al livello di quale gruppo di caselle è stato assemblato, o fino allo stato totale del programma.) Ad esempio il contenuto all'interno una \begin{tikzpicture} … \end{tikzpicture}
è improbabile che dipenderà molto dallo stato TeX come la pagina contatore del numero, così quando abbiamo ricompilare il documento TeX possiamo semplicemente riutilizzare tutto il lavoro - se abbiamo tenuto traccia di informazioni sufficienti per sapere che è sicuro farlo. (Naturalmente TikZ in particolare ha modi di esternare questo e includere i risultati, ma l'idea è più generale.)
Possiamo usare tecniche (ad es. Quelle usate nella programmazione funzionale) per eseguire alcune elaborazioni TeX con "buchi" - ad es. Proprio ora, quando scrivi \ref{foo}
in LaTeX per fare riferimento a un numero di sezione (diciamo futuro), funziona solo in due passaggi di compilazione: prima viene elaborato l'intero documento (tutti i paragrafi composti, float posizionati su pagine, ecc.) con i numeri di sezione scritti in un file ausiliario, quindi con un secondo passaggio tuttoil lavoro viene ripetuto, con il numero di sezione effettivamente disponibile questa volta. (Questo tipo di hack potrebbe essere stato inevitabile al momento, e so che l'impatto sul tempo di esecuzione è "solo un fattore costante", ma ...) Invece, se potessimo semplicemente elaborare il documento con un "buco" ( una casella con contenuti indeterminati ma con una larghezza stimata) rimasta per il numero di sezione, quindi alla fine dell'elaborazione del documento popolare la casella? (Sì, la nostra larghezza stimata potrebbe risultare errata e il paragrafo potrebbe dover essere rielaborato e, di conseguenza, anche la pagina, ma potremmo fare il lavoro, se necessario, o accettare, per la velocità, una modalità in cui consentiremo una larghezza errata per il numero della sezione.)
Tecniche simili possono funzionare per l'editing interattivo di un documento TeX: quando modifichi un paragrafo può essere elaborato "dal vivo", con i paragrafi futuri semplicemente spostati nella cambusa (diciamo). Sappiamo che è possibile, poiché esistono già implementazioni (commerciali) di TeX che lo fanno, ad esempio BaKoMaTeX e Texpad e le precedenti Textures . (Vedi il video sulla home page di BaKoMa-TeX e in modo simile a quello di TeXpad, ad esempio questo video - ho provato quest'ultimo ed era insopportabilmente difettoso in pratica.)
Da non sottovalutare: il valore di mostrare le cose all'utente, rendendo TeX più debuggabile. In questo momento, gli utenti vedono solo i loro input di TeX e non hanno idea esattamente di cosa sta lavorando TeX, ad esempio quanto tempo impiega a interrompere la linea per i paragrafi, o alla macro-espansione (e di quali macro), quali scatole sta assemblando e buttando via, quali speciali vengono scritti da quale pacchetto, ecc. Io (forse ottimisticamente) credo che esistano utenti che vorrebbero vedere queste informazioni e troverebbero utile, ad esempio, sapere se lo strano pacchetto che stanno usando per l'ombreggiatura le equazioni con una sfumatura sullo sfondo sono economiche (aggiungendo poco al tempo di elaborazione) o meno. Vedendo dove viene svolto un sacco di lavoro dispendioso, potrebbero buttarne via parte (almeno fino alla loro ultima stampa). (È un po 'come compilatori o altri strumenti che inseriscono informazioni di profilazione nei programmi.) Rendere TeX più trasparente e debuggabile può essere un enorme miglioramento dell'usabilità, per esempio. (TeX è già abbastanza user-friendly e debuggable per il suo tempo IMO se usiamo TeX per lo più semplice con pochissime macro, ma non con LaTeX o come la maggior parte degli utenti lo incontra oggi.)
Inoltre, qualsiasi lavoro futuro dovrebbe probabilmente prendere in considerazione (costruire) LuaTeX, che è la migliore modifica di TeX che abbiamo attualmente.
Tutti questi sono solo pensieri oziosi (non ne ho implementato nessuno, per conoscere lo sforzo richiesto o la velocità che avremmo guadagnato), ma spero che questo possa in qualche modo rispondere alla tua domanda o darti idee per direzioni future .