Interface LaTeX3 pour les fonctions
J'ai récemment posté une question sur l'écriture d'une macro en TeX brut qui modifierait les éléments d'une liste spécifiée par l'utilisateur. J'ai mentionné de façon désinvolte mon aversion pour l'interface de TeX, alors quelqu'un m'a tourné vers LaTeX3, qui est censé être, comme le manuel le promet, plus comme un langage de programmation moderne. Je commence juste à programmer dans TeX, donc ça a été une bataille difficile d'essayer de comprendre le manuel. Je suppose que c'est parce que le manuel a été écrit pour des utilisateurs TeX expérimentés; cependant, il ne semble pas y avoir d'alternative pour les personnes débutant dans LaTeX3 / TeX, donc je n'ai pas d'autre choix que de travailler avec ce que j'ai. C'est pourquoi je poste ceci. Le manuel est déroutant, et j'aimerais dissiper une partie de cette confusion en vous posant quelques questions simples sur la syntaxe.
Je dois mentionner que la personne qui m'a parlé de LaTeX3, m'a également donné une solution à mon message d'origine en utilisant son interface. J'ai pu utiliser cette solution en conjonction avec le manuel pour commencer à élaborer quelques faits de base sur la syntaxe LaTeX3. Je vais parler de ce que j'ai réussi à comprendre, mais attention, certaines d'entre elles sont basées sur mes propres inférences - dessinées à l'aide de l'exemple fourni par l'utilisateur de stackexchange - pas d'instructions explicites dans le manuel, alors attendez-vous à des erreurs. J'aimerais que vous sachiez que je ne brouille pas les choses quand j'utilise parfois ma propre terminologie. C'est juste difficile de parler d'un sujet que vous ne comprenez pas complètement de manière structurée.
J'écris aussi ceci comme un article séparé, pas comme un commentaire, en raison de sa longueur. Merci d'avance.
-------------------------------------------------- -------------------------------------------------- -------------------
Définitions des fonctions .
Ce que j'ai réussi à comprendre jusqu'à présent :
Une nouvelle fonction est définie, entre autres, avec le code suivant:
\cs_new_<restrictions>:Npn <function name> <function parameters> {<replacement code>}
C'est \cs_new_<restrictions>une commande LaTeX, le Npn est là pour dire à "l'analyseur" de l'interface ce à quoi il doit s'attendre après la \cs_new_<restrictions>: Npnpartie du code, dans ce cas, un seul mot de contrôle de jeton, c'est <function name>-à- dire un ou plusieurs paramètres, c'est <function parameters>-à- dire et un jeton list, c'est-à-dire {<code>}qui remplace la fonction.
Donc, si je veux définir une nouvelle fonction qui prend, disons, 4 arguments, je pourrais m'y prendre avec le code suivant
\cs_new_<restrictions>:Npn \myfunction #1 #2 #3 #4 {<code>}
Et de même, le code d'une fonction avec 2 arguments pourrait ressembler à ceci
\cs_new_<restrictions>:Npn \myfunction #1 #2 {<code>}
Bien sûr, je suppose - et corrigez - moi si je me trompe - les espaces ne sont pas nécessaires, parce que l'analyseur a déjà été dit comment les arguments « délimiter meta » ( <function name>, <parameters>, {<code>}) les uns des autres avec l'aide de la "méta signature" Npn .
Maintenant, si je veux me débarrasser des #, je peux utiliser la commande générique suivante
\cs_new_<restrictions>:Nn <function name>:<function signature> {<code>}
<function signature>Accord similaire, sauf que maintenant l'analyseur attend un comme Nn, NnN, TnN ou quelque chose ou autre, après <function name>.
Encore une fois, une fonction avec 4 arguments pourrait ressembler à ceci
\cs_new_<restrictions>:Nn \myfunction:NNNN {<code>}
et un avec 2 arguments comme celui-ci
\cs_new_<restrictions>:Nn \myfunction:NN {<code>}
Il existe d'autres commandes dans la bibliothèque l3basics pour créer des fonctions, mais leur structure générale semble être essentiellement la même. La seule différence réside dans leur fonctionnalité. Ainsi, par exemple, utiliser \cs_set...au lieu de \cs_new...rend la fonction locale par opposition à globale. J'écrirai probablement un post de suivi demandant plus de détails sur ce que sont les extensions de type e et de type x, mais pour l'instant, je pense qu'il est préférable de s'en tenir à une vue d'ensemble.
De toute façon, est-ce vrai jusqu'à présent?
D'accord, continuez.
Définitions de variables .
Ce que j'ai réussi à comprendre jusqu'à présent :
Il y a donc pas mal de types de données dans LaTeX3, mais les principaux sont des listes de jetons , des chaînes , des entiers , des séquences et des listes séparées par des virgules . Ils utilisent chacun leurs propres abréviations, mais en général, lors de la définition d'une nouvelle variable, vous déclarez le type et le suivez avec un mot-clé comme new ou const selon que vous initialisez la variable.
Donc, par exemple, si je veux déclarer, mais pas initialiser, une variable de liste de jetons, j'utilise le code:
\tl_new:N \mytokenList
puis quelque part sur la ligne, je peux stocker une liste de jetons \mytokenListavec le code:
\tl_set:Nn \mytokenList {<tokens>}
Mais, si je sais quelles données je veux stocker dans la variable dès le départ, je peux à la place utiliser cette commande (ne s'applique pas aux séquences ou aux entiers )
\tl_const:Nn \mytokenList {<tokens>}
A part: j'ai remarqué que même les variables ont des "signatures de fonction". Facilite probablement la définition d'un régime d'analyse.
C'est à peu près aussi général que possible, avant de devoir spécifier le type de données auquel je fais référence, car chacun a ses propres opérations associées.
-------------------------------------------------- -------------------------------------------------- -------------------
C'est ce que j'ai jusqu'à présent. J'apprécierais vos commentaires. Ce n'est pas facile à apprendre par vous-même! Surtout avec une connaissance minimale de TeX, donc je m'excuse si certains d'entre vous regardent cela et pensent "bien évidemment". Quoi qu'il en soit, merci encore.
Réponses
Il existe deux manières principales de définir des fonctions:
\cs_new<restrictions>:Npn
\cs_new<restrictions>:Nn
où peut être _protected, _noparou _protected_nopar.
Les deux méthodes vérifient que l' Nargument (c'est-à-dire un seul jeton) qui suit est une séquence de contrôle (ou un caractère actif) actuellement indéfini et définissent globalement la séquence de contrôle.
Quelle est la différence? Que la première famille nécessite, après la séquence de contrôle à définir, un «texte de paramètre» avant de {délimiter le «texte de remplacement» de la fonction.
Le «texte de paramètre» peut être n'importe quelle séquence de jetons, y compris #1, #2et ainsi de suite jusqu'à #9. Cependant, pour apprécier toute la puissance de cette liberté, vous devez vous familiariser avec le chapitre 20 du TeXbook et le concept d '«argument délimité».
Restons simples, cependant. Les deux morceaux de code suivants sont complètement équivalents:
\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Nn \harry_foo:nn { -#1-#2- }
car ce dernier fournira automatiquement le texte du paramètre en #1#2fonction de la signature de la fonction à définir, dans ce cas :nn.
La signature doit être constituée d'une séquence (éventuellement vide) de caractères net N.
Notez que les espaces sont ignorés lorsque \ExplSyntaxOnest actif, donc
\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2{ -#1-#2- }
sont tous équivalents. Il pourrait y avoir un espace même après #, mais je ne le recommanderais pas.
Les règles de syntaxe de TeX spécifient que lorsqu'il attend un «texte de paramètre» (en gros, lors d' \defassignations ou similaires et après avoir stocké le nom de la macro à définir), tout jusqu'au premier {fait partie du texte du paramètre. Il n'y a aucun moyen de prévoir ce qu'est le texte du paramètre, d'où le spécificateur d' pargument spécial qui signifie simplement «tout jusqu'à {».
Seul un texte de paramètre simple tel que #1, #1#2etc. peut être généré automatiquement, ce qui est fait lorsque l'on utilise la deuxième famille \cs_new<restrictions>:Nn.
Où vous trompez-vous? En supposant que vous pouvez utiliser Tcomme spécificateur dans la signature. Les spécificateurs d'argument Tou Fsont ajoutés lors de l' \prg_new_conditional<restrictions>:Nnnexécution.
De plus, votre analyse du texte du paramètre est erronée, comme indiqué précédemment.
Et \cs_set<restrictions>:Npnet :Nn? Tout comme ci-dessus s'applique, à la différence que la fonction à définir n'est pas vérifiée pour être définie ou non et sa signification sera écrasée silencieusement, mais la portée de la déclaration coïncide avec le groupe courant. En règle générale, \cs_set...est utilisé pour les fonctions temporaires qui doivent s'adapter au contexte afin que leur signification ne soit pas fixe.
Les conventions de dénomination des variables recommandent que leur nom commence par l, gou c. En fait, les variables utilisées dans le expl3code doivent être conformes à la convention; il est possible d'utiliser des noms «normaux» comme \myTokenListpour les variables de type tl(peut-être aussi clist) qui doivent être utilisées dans le document.
Les variables commençant par ldoivent toujours être appliquées localement (par \tl_set:Nnexemple), tandis que les variables commençant par gdoivent toujours être utilisées globalement (par \tl_gset:Nnexemple).
Les variables commençant par csont des constantes et ne doivent jamais être utilisées après avoir reçu une valeur, mais uniquement utilisées.
On peut définir des constantes avec
\tl_const:Nn \c_harry_foo_tl {<tokens>}
\str_const:Nn \c_harry_foo_str {<tokens>}
\clist_const:Nn \c_harry_foo_clist {<comma list>}
\seq_const_from_clist:Nn \c_harry_foo_seq {<comma list>}
\prop_const_from_keyval:Nn \c_harry_foo_prop {<key-value list>}
\int_const:Nn \c_harry_foo_int {<integer expression>}
\fp_const:Nn \c_harry_foo_int {<fp expression>}
\bool_const:Nn \c_harry_foo_bool {<boolean expression>}
\dim_const:Nn \c_harry_foo_dim {<dimen expression>}
\skip_const:Nn \c_harry_foo_dim {<skip expression>}
\muskip_const:Nn \c_harry_foo_dim {<muskip expression>}
\intarray_const_from_clist:Nn \c_harry_foo_intarray {<comma list>}
\regex_const:Nn \c_harry_foo_regex {<regex>}
\cc_tab_const:Nn \c_harry_foo_cctab {<code>}