<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">% Time-stamp: &lt;2019-09-24 10:47:32 administrateur&gt;
% 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 Ã&nbsp; \Expliii{}, ce que je
fais dÃ¨s la premiÃ¨re ligne qui n'est pas un commentaire Ã&nbsp; 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 Ã&nbsp; Ãªtre appelÃ©e directement dans
un document rÃ©digÃ© par l'utilisateur final. On y voit dÃ©jÃ&nbsp; 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Ã&nbsp; 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 Ã&nbsp; rien sur
  cette commande et un utilisateur du \gls{module} ne doit pas
  s'attendre Ã&nbsp; ce que le comportement de cette commande reste stable
  au fil des versions ni mÃªme Ã&nbsp; 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Ã&nbsp;
    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, Ã&nbsp; 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Ã&nbsp; dÃ©finie et produit une erreur si c'est le cas. De plus, elle
dÃ©finit la commande de maniÃ¨re globale \TO penser Ã&nbsp; \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 Ã&nbsp; 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\) Ã&nbsp;~\(10\)\TF, je crÃ©e
deux \glspl{booleen} \TO \Macro{yh_continue_bool} et
\Macro{yh_est_premier_bool}\TF Ã&nbsp; 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, Ã&nbsp; 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 Ã&nbsp; ma devise\footnote{Ã€ savoir: \og ceinture et
  bretelles\fg.}, je coure le risque que ces deux \glspl{booleen}
existent dÃ©jÃ&nbsp;, 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
Ã&nbsp; 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 Ã&nbsp; 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 Ã&nbsp; 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\) Ã&nbsp; la valeur courante de
\Macro{l_tmpa_int} Ã&nbsp; 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 |&gt;|, |&lt;| 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 Ã&nbsp; 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} Ã&nbsp;~\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 Ã&nbsp;
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 Ã&nbsp;
faire, s'il est premier, on le retourne. Cela est accompli Ã&nbsp; 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Ã&nbsp; 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 } &amp;&amp;
  (
    \int_compare_p:n { 2 = 3 } ||
    \int_compare_p:n { 4 &lt;= 4 } ||
    \str_if_eq_p:nn { abc } { def }
  ) &amp;&amp;
! \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 Ã&nbsp; 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 Ã&nbsp; 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 Ã&nbsp; 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 Ã&nbsp; 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 Ã&nbsp; 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 Ã&nbsp; ce qu'ils aient une valeur pertinente Ã&nbsp; l'extÃ©rieur
du groupe.

Pour respecter ce caractÃ¨re local, je donne Ã&nbsp; 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, Ã&nbsp; 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\) Ã&nbsp; l'aide de \Macro{cs_undefine:N}.

Il est temps Ã&nbsp; 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 Ã&nbsp; Oxford on a fini par
  renoncer Ã&nbsp; 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} Ã&nbsp;~\(3\). On a dÃ©jÃ&nbsp; 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Ã&nbsp; expliquÃ© ci-dessus l'utilitÃ© des lignes~\(57\) Ã&nbsp;~\(59\).

\subsection{Utilisation de la commande de document}
\label{sec:utilisation}

Il me reste Ã&nbsp; 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{} Ã&nbsp; \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 Ã&nbsp; peine
effleurÃ© ci-dessus\TF, Ã&nbsp; elle seule, peut inciter Ã&nbsp; passer Ã&nbsp;
\Expliii{} pour crÃ©er ses propres macros.

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "dun19expl3"
%%% End:
</pre></body></html>