summaryrefslogtreecommitdiff
path: root/info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-03-22 03:00:48 +0000
committerNorbert Preining <norbert@preining.info>2020-03-22 03:00:48 +0000
commit75d8dfa80524727ddb7d8ae217ed6463efba84cf (patch)
treea1a1db248828dd36aecb1697d64d28a2ff813d29 /info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex
parent3e43bc594a14e8c4fc21d6a71f22a23dd78fe252 (diff)
CTAN sync 202003220300
Diffstat (limited to 'info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex')
-rw-r--r--info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex400
1 files changed, 400 insertions, 0 deletions
diff --git a/info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex b/info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex
new file mode 100644
index 0000000000..cff913ae23
--- /dev/null
+++ b/info/expose-expl3-dunkerque-2019/dk19ecrireprem.tex
@@ -0,0 +1,400 @@
+% Time-stamp: <2019-09-24 10:47:32 administrateur>
+% Création : 2019-08-24T14:29:55+0200
+\section{Rappel}
+\label{sec:rappel}
+
+Je commence par redonner le code de Donald E. \textsc{Knuth} mais je
+laisse le lecteur rechercher l'article précité de Denis \textsc{Roegel}
+pour y trouver toutes les explications nécessaires.
+
+\VerbatimInput[frame=lines, framesep=0.75\baselineskip,
+label={\textsc{Knuth} \textemdash{} \emph{définitions}},
+labelposition=topline]{./codes/knuth-def.tex}
+
+L'appel |\primes{15}| permet d'obtenir
+\og \primes{15}\fg.
+
+\section{Version avec \Expliii}
+\label{sec:versionexpl3}
+
+
+Commençons par quelques remarques: comme le code est écrit dans un
+fichier \texttt{.tex} \TO et non dans un \gls{module} \TF je dois
+commencer par enclencher la syntaxe propre à \Expliii{}, ce que je
+fais dès la première ligne qui n'est pas un commentaire à usage
+interne \TO d'où le décalage de numéro \TF dans le premier fragment
+ci-dessous:
+%
+\Fragment{3}{5}{./codes/henel-def}
+
+\subsection{Une macro privée pour écrire les nombres}
+\label{sec:macro+ecrire+entier}
+
+Sur la ligne~\(5\), on lit la définition d'une macro \emph{interne}
+\CAD d'une macro qui n'a pas vocation à être appelée directement dans
+un document rédigé par l'utilisateur final. On y voit déjà quelques
+différences avec du code \LaTeXe{} que je vais préciser maintenant:
+\begin{itemize}
+\item les caractères |_| et~|:| sont promus au rang de lettres mais
+ par l'arobase~|@| cher aux programmeurs en~\LaTeXe{};
+
+\item les espaces du code ne donneront pas d'espace dans le
+ document. Voilà qui soulage grandement le programmeur puisque
+ disparait la phase de recherche des \TdSTrad{blancs
+ inopportuns}{spurious blanks}.
+\end{itemize}
+
+Autre remarque, d'ordre typographique, la présentation que j'adopte
+dans ce document \TO pour des raisons de place\TF n'est pas la
+présentation recommandée par l'équipe du projet \LaTeX3. On devrait
+plutôt, en effet, adopter la présentation qui suit\index{présentation
+ du code}:
+%
+\begin{Verbatim}[frame=lines, framesep=0.75\baselineskip]
+\cs_new:Nn \__yh_ecrire_nombre:n
+ {
+ \(\np{\int_to_arabic:n{ #1 }}\)
+ }
+\end{Verbatim}
+%
+dont on m'accordera, j'espère, qu'elle occupe plus d'espace.
+
+La commande que je définis s'appelle
+\Macro{__yh_ecrire_nombre:n}. Ce nom comporte plusieurs parties:
+\begin{enumerate}
+
+\item les \og |__|\fg initiaux signalent que cette commande est
+ \emph{privée} \CAD que son usage est réservée au \gls{module} \TO
+ ici le simple fichier contenant le code\TF et n'est pas
+ nécessairement documentée. Le programmeur ne s'engage à rien sur
+ cette commande et un utilisateur du \gls{module} ne doit pas
+ s'attendre à ce que le comportement de cette commande reste stable
+ au fil des versions ni même à ce qu'elle soit toujours
+ disponible. Il ne s'agit ici que d'une \textsb{convention} car
+ \TeX{} est resté ce qu'il est et la gestion des espaces de noms
+ n'est pas implémentée\footnote{L'équipe des développeurs de
+ \Expliii{} nous dit, dans \autocite[p.~1]{expl3progr} que celà
+ pourrait se faire mais avec un surcoût prohibitif.};
+
+\item \og |yh|\fg remplace ici ce qui est \TO dans un \gls{module}\TF
+ le nom du \gls{module} ou, à tout le moins, une chaine de caractères
+ réservée pour ce \gls{module};
+
+\item vient le nom explicite de la commande: \og |ecrire_nombre|\fg
+ dans lequel le souligné~\og |_|\fg sert de séparateur de mots;
+
+\item suivi du caractère~\og |:|\fg qui introduit la \gls{signature}
+ de la commande qui est, ici, \og |n|\fg. Cela nous indique que la
+ commande est une \gls{fonction} \TO c'est le vocabulaire défini par le
+ projet \LaTeX3\TF qui attend un seul argument fourni entre
+ accolades.
+\end{enumerate}
+
+La fonction \Macro{cs_new:Nn} utilise la \gls{signature} de la
+commande qui suit pour déterminer le nombre et le type des arguments
+que demande cette commande. Elle vérifie que la commande n'est pas
+déjà définie et produit une erreur si c'est le cas. De plus, elle
+définit la commande de manière globale \TO penser à \Macro{gdef} avec
+les pouvoirs de \Macro{newcommand}\TF.
+
+Elle possède plusieurs variantes dont, \PX{}, \Macro{cs_new:cn} qui
+attend comme premier argument le \emph{nom} de la commande plutôt que
+la commande elle-même. J'aurais obtenu le même résultat avec:
+%
+\begin{Verbatim}[frame=lines, framesep=0.75\baselineskip]
+\cs_new:cn { __yh_ecrire_nombre:n } { \(\np{\int_to_arabic:n{ #1 }}\) }
+\end{Verbatim}
+%
+code que je livre compacté.
+
+Le 2\ieme argument de \Macro{cs_new:Nn} doit être fourni entre
+accolades, c'est la définition de la commande. Ici j'utilise
+\Macro{np} de l'extension \Pkg{numprint} en mode mathématique en
+ligne \TO à l'aide du bien connu couple |\(| et~|\)| \TF afin
+d'obtenir \og \(\np{3257}\)\fg au lieu de \og \(3257\)\fg.
+
+La \gls{fonction} \Macro{int_to_arabic:n} appartient au \gls{module}
+\Mdl{int}, partie du noyau de \LaTeX3, qui regroupe les commandes
+traitant les \glspl{entier}. Elle prend un argument dont elle fournit
+la représentation en chiffres \emph{arabes}.
+
+\subsection{Commande vérifiant qu'un entier impair est premier}
+\label{sec:macro+impair+premier}
+
+La commande \Macro{yh_impair_est_premier:nT} ne se déclare pas comme
+privée, dans un \gls{module} elle devrait avoir une interface et une
+sortie stable et être documentée car son nom ne commence pas par~|__|
+mais ça aurait pu être le cas.
+
+\(2\) étant le seul nombre pair premier, la question de la primarité
+ne se pose vraiment que pour les entiers impairs. Je pourrai donc
+n'essayer que des diviseurs impairs.
+
+La \gls{signature} de cette \gls{fonction}, \CAD |nT|, nous indique
+qu'elle attend deux arguments entre accolades, que le 1\ier sera un
+test qui renverra soit~\VRAI{} soit~\FAUX{} et que, \emph{dans le seul
+ cas} où le test est~\VRAI{}, le code contenu dans la 2\ieme paire
+d'accolades sera considéré.
+
+Regardons le code:
+%
+\Fragment{7}{25}{./codes/henel-def}
+
+Dans la partie d'initialisation \TO lignes~\(8\) à~\(10\)\TF, je crée
+deux \glspl{booleen} \TO \Macro{yh_continue_bool} et
+\Macro{yh_est_premier_bool}\TF à l'aide de la \gls{fonction}
+\Macro{bool_set_true:N} qui, dans le même temps, leur donne la
+valeur~\VRAI.
+
+Les \glspl{fonction} dont le nom contient |set| définissent les
+commandes sans vérification et, à moins que le nom contienne |gset|
+\TO |g| comme \og global\fg\TF, elles créent ces commandes
+\emph{localement} \CAD{} dans le groupe où a lieu la définition.
+
+Ici, contrairement à ma devise\footnote{À savoir: \og ceinture et
+ bretelles\fg.}, je coure le risque que ces deux \glspl{booleen}
+existent déjà, risque dont je pense qu'il est faible. On verra plus
+bas ce que j'aurais pu faire pour sécuriser la définition.
+
+Ces deux \glspl{booleen} ne sont pas des \glspl{fonction} mais des
+\glspl{variable} \CAD{} des macros \TO au sens de \TeX{}\TF dont le
+seul objet est de contenir une valeur et non pas de \emph{faire}
+quelque chose. C'est pour cela que leurs noms n'ont pas de
+\gls{signature} et ne se termine pas par~|:| qui signalerait une
+\gls{fonction} sans argument.
+
+Dernière étape de l'initialisation, avec \Macro{int_set:Nn} je donne
+à la variable entière \textbf{l}ocale temporaire \Macro{l_tmpa_int}
+la valeur~\(1\). Plusieurs \glspl{module} du noyau de \LaTeX3
+fournissent deux variables locales dont les noms comportent |tmpa|
+et~|tmpb| respectivement et deux variables \textbf{g}lobales \TO avec
+les noms équivalents\TF.
+
+Suivant la convention générale qui veut que le nom d'une
+\gls{variable} se termine par son type \TO c'est le cas des deux
+\glspl{booleen} que j'ai définis\TF, les variables temporaires
+fournies par un \gls{module} du noyau ont une finale qui donne le type
+comme \Macro{l_tmpa_int}. Cependant, contrairement à cette même
+convention de nommage, les variables temporaires n'ont pas, en tête de
+nom, le nom du module. On aura voulu éviter quelque chose comme
+\Macro*{int_l_tmpa_int} dont on peut penser que c'est légèrement
+redondant.
+
+En ligne~\(12\), je commence une boucle \TANTQUE avec
+\Macro{bool_do_while:Nn} qui attend un premier argument constitué d'un
+seul lexème \TO ici \Macro{yh_continue_bool} qui est~\VRAI à l'entrée
+dans la boucle\TF et un deuxième argument entre accolades: le corps de
+la boucle.
+
+Le corps de cette boucle commence avec l'accolade ouvrante du bout de
+la ligne~\(12\) et s'achève avec la 2\ieme accolade fermante de la
+ligne~\(24\).
+
+Je commence par ajouter~\(2\) à la valeur courante de
+\Macro{l_tmpa_int} à l'aide de la \gls{fonction} \Macro{int_add:Nn};
+\Macro{l_tmpa_int} est ici le candidat diviseur.
+
+\Macro{bool_if:nTF} est une forme de~\SIALORSSINON: on a bien les deux
+branches de l'alternative puisque la signature se termine en~|TF|. Il
+s'agit de savoir si le candidat est bien un diviseur de l'entier
+représenté par~|#2|. Pour ce faire, j'utilise la \gls{fonction}
+\Macro{int_compare_p:nNn} dont le 2\ieme argument est un opérateur de
+comparaison \CAD |>|, |<| ou~|=|. Le 3\ieme argument est
+simplement~\(0\). Le premier, lui, est le reste de la division de~|#2|
+par \Macro{l_tmpa_int} que l'on obtient à l'aide de la \gls{fonction}
+\Macro{int_mod:nn}.
+
+Si le reste est nul, on exécute le code du 2\ieme argument de
+\Macro{bool_if:nTF}. On positionne les deux \glspl{booleen} à~\FAUX{}
+puisque |#2|, divisible par \Macro{l_tmpa_int}, n'est pas premier et
+qu'il n'est donc pas nécessaire de reprendre la boucle.
+
+Si le reste n'est pas nul, je compare l'entier~|#2| et le carré du
+candidat \TO on peut utiliser les opérateurs \emph{classiques}
+d'opérations: |+|, |-|, |*|, |/| car, derrière ce code, c'est le
+mécanisme de la macro \Macro{numexpr} de \hologo{eTeX} qui est à
+l'œuvre\TF. Si le carré est plus grand, c'est que |#2|~est premier et
+qu'il est temps de s'arrêter d'où les valeurs données aux deux
+\glspl{booleen}. Le 3\ieme argument du \Macro{bool_if:nTF} s'arrête
+avec la 1\iere accolade fermante de la ligne~\(24\).
+
+À la sortie de la boucle, si |#2| n'est pas premier il n'y a rien à
+faire, s'il est premier, on le retourne. Cela est accompli à l'aide
+de la \gls{fonction} \Macro{bool_if:nT} qui réalise un saut
+conditionnel \SIALORS.
+
+\subsubsection{Compléments}
+\label{sec:complementbouclesaut}
+
+Outre les deux \glspl{fonction} \Macro{bool_if:nTF} et
+\Macro{bool_if:nT}, \Expliii fournit également la \gls{fonction}
+\Macro{bool_if:nF} qui réalise un saut conditionnel \SISINON. Dans le
+manuel, on verra que la signature se termine
+par~\underline{\texttt{\emph{TF}}} pour signaler la présence des trois
+signatures~|T|, |F| et~|TF|.
+
+Par ailleurs, \Expliii fournit essentiellement quatre boucles:
+\begin{itemize}
+\item \Macro{bool_do_while:Nn}, déjà rencontrée. C'est un \TANTQUE
+ dont le corps est exécuté puis le test effectué \CAD qu'en toutes
+ circonstances, le corps est exécuté au moins une fois;
+
+\item \Macro{bool_do_until:Nn}, qui inverse le sens du test. C'est un
+ \JUSQUA dont le corps est exécuté au moins une fois;\label{booldountilNn}
+
+\item \Macro{bool_while_do:Nn}, \TANTQUE qui commence par le
+ test. Il se peut donc que le corps ne soit pas exécuté;
+
+\item \Macro{bool_until_do:Nn}, \JUSQUA commençant par le
+ test.
+\end{itemize}
+
+Ces quatres \glspl{fonction} ont des variantes de signatures~|cn|
+et~|nn|. Avec~|cn|, le 1\ier argument est le nom d'un \gls{booleen};
+avec~|n|, c'est une expression booléenne comme \TO exemple tiré de
+\autocite{l3interfaces}\TF
+%
+\begin{Verbatim}[frame=lines, framesep=0.75\baselineskip]
+\int_compare_p:n { 1 = 1 } &&
+ (
+ \int_compare_p:n { 2 = 3 } ||
+ \int_compare_p:n { 4 <= 4 } ||
+ \str_if_eq_p:nn { abc } { def }
+ ) &&
+! \int_compare_p:n { 2 = 4 }
+\end{Verbatim}
+%
+qui permet de mesurer la complexité acceptée.
+
+\subsection{Écrire la liste des nombres premiers}
+\label{sec:ecrirelistepremiers}
+
+Avant d'aborder la commande destinée à l'utilisateur \TO dont je dirai
+que c'est une \emph{commande de document}, comme le suggère le nom de
+la macro qui permettra de la créer tout à l'heure. L'extension
+\Pkg{xparse}~\autocite{xparse} parle de \English{document-level
+ command}\TF, je présente deux nouvelles macros utilitaires \TO
+qui elles aussi auraient pu être \emph{privées}\TF à savoir
+\Macro{yh_ecrire_separateur:n} et \Macro{yh_ecrire_si_premier:n}.
+
+\subsubsection{Deux macros utilitaires}
+
+\Fragment{27}{32}{./codes/henel-def}
+
+On voit dans le code ci-dessus, en ligne~\(27\), une pré-déclaration
+de \Macro{yh_ecrire_separateur:n} qui permet juste de s'assurer que ce
+nom est bien disponible.
+
+La macro suivante \Macro{yh_ecrire_si_premier:n} fait exactement ce
+que son nom suggère.
+
+Passons maintenant à la commande principale.
+
+\subsubsection{La commande de document}
+\label{sec:commandededocument}
+
+\Fragment{34}{59}{./codes/henel-def}
+
+Le code permettant de définir cette commande utilise l'extension
+\Pkg{xparse}~\autocite{xparse} et sa macro \Macro{NewDocumentCommand}.
+
+La syntaxe de déclaration d'argument change quelque peu! Le |m|,
+2\ieme argument de la macro, indique que l'on définit une commande
+requérant un unique argument obligatoire fourni entre accolades \TO
+|m| pour \English{mandatory} \CAD \og obligatoire\fg\TF.
+% Le 1\ier argument est attendu \textsb{entre accolades} \TO pas de
+% fantaisie à la \LaTeXe{}, du genre |\new|\0|com|\0|mand|
+% |\truc|\dots{}, ici\TF. FAUX!
+Le 1\ier argument est, comme on s'y attend, le nom de la commande
+créée.
+
+Le corps de la définition commence en ligne~\(35\) en ouvrant un
+groupe avec \Macro{group_begin:} et finit en ligne~\(59\) en fermant
+le groupe avec \Macro{group_end:}.
+
+\paragraph{Initialisation}
+
+Dans le groupe, je crée en lignes~\(37\) et~\(38\) deux \glspl{entier}
+locaux \TO d'où le |l| initial\TF mais qui seront créés
+\emph{globalement}, car il n'y a pas moyen de faire autrement. Leur
+caractère local est donc conventionnel mais signale que l'on ne doit
+pas s'attendre à ce qu'ils aient une valeur pertinente à l'extérieur
+du groupe.
+
+Pour respecter ce caractère local, je donne à ces \glspl{entier}, une
+valeur avec \Macro{int_set:Nn} et pas avec \Macro{int_gset:Nn} qui, de
+fait, n'est qu'un alias de la première, à moins que ce soit
+l'inverse\footnote{Je ne suis pas allé vérifier dans le
+ source~\autocite{source3}.}.
+
+Afin que, en sortie de commande, ces deux \glspl{entier} ne soient
+plus accessibles \TO \textsl{Vous êtes priés de laisser ces lieux dans l'état
+où vous auriez aimé les trouver en entrant!} \TF, je les annihile en
+lignes~\(57\) et~\(58\) à l'aide de \Macro{cs_undefine:N}.
+
+Il est temps à présent de définir, localement, avec \Macro{cs_set:Nn},
+la fonction \Macro{yh_ecrire_separateur:n}, ce que je fais en
+ligne~\(41\) et~\(42\). Comme la définition est faite dans une
+définition, on doit, bien entendu, recourir au doublement des
+\emph{dièses} d'où le |##1| dans le code de cette fonction.
+
+Dans les 1\ier et 3\ieme arguments de \Macro{int_compare:nNnTF} on
+peut écrire \emph{naturellement} des opérations sur les entiers. Je ne
+m'en prive pas.
+
+Les tildes~|~| que l'on voit apparaitre en ligne~\(42\) permettent de
+coder un espace qui apparaitra dans le document final. Par contre, il
+faut utiliser autre chose pour coder un espace insécable \TO la
+solution est la macro \Macro{nobreakspace}\TF.
+
+Je suis obligé de regarder si le séparateur est le dernier car, en
+français\footnote{Encore que, si j'ai bien compris un article récent
+ paru dans la presse britanique, même à Oxford on a fini par
+ renoncer à la virgule devant le \emph{and} précédant le dernier mot
+ d'une énumération. \textsl{Tout fout l'camp, ma bonne dame!}} il ne
+doit pas y avoir de virgule devant le \emph{et}.
+
+Comme l'annonce la ligne~\(43\) je ne calcule pas les deux premiers
+nombres premiers \TO Donald \textsc{Knuth} ne le faisait pas\TF et je
+ne vérifie pas que l'utilisateur demande au moins trois nombres \TO
+même remarque\TF; pour faire comme dans les livres sérieux, je laisse
+cette amélioration comme exercice pour le lecteur.
+
+Je prépare maintenant la boucle en initialisant, localement, le
+\emph{candidat premier} à~\(3\). On a déjà vu \Macro{int_set:Nn}.
+Et je rentre dans la boucle en ligne~\(50\) pour en sortir en
+ligne~\(55\). La seule nouveauté de ce fragment de code est l'emploi
+de \Macro{int_incr:N} qui permet d'incrémenter localement le compteur
+\Macro{l_compteur_int}.
+
+J'ai déjà expliqué ci-dessus l'utilité des lignes~\(57\) à~\(59\).
+
+\subsection{Utilisation de la commande de document}
+\label{sec:utilisation}
+
+Il me reste à utiliser cette commande dans ce document:
+|\ListePremiers{15}| produit \og \ListePremiers{15}\fg.
+
+Au passage, on notera avec satisfaction que |\primes| et
+|\ListePremiers| sont d'accord quant aux quinze premiers nombres
+premiers. C'est rassurant.
+
+\subsection{Quelques commentaires subjectifs}
+\label{sec:commentairessubjectifs}
+
+J'accorde sans peine qu'avec \Expliii le code est plus verbeux qu'avec
+\TeX{} tout seul. Je ne peux, cependant, m'empêcher de penser qu'il
+est plus clair. Pour ma part, le gain énorme que je vois en passant
+cette fois de \LaTeXe{} à \Expliii{} c'est le systématisme du nommage
+des macros, \glspl{fonction} ou \glspl{variable}. L'équipe du projet
+\LaTeX3 en fait d'ailleurs, elle-même, un ``\emph{argument de
+ vente}''.
+
+La puissance de \Macro{NewDocumentCommand} \TO que l'on a à peine
+effleuré ci-dessus\TF, à elle seule, peut inciter à passer à
+\Expliii{} pour créer ses propres macros.
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "dun19expl3"
+%%% End: