|
Bonjour, ma précédente et éphémère question a été retirée car il s'agissait une erreur bête de ma part, mais là j'aurais un souci (ou une demande) que je n'arrive pas à gérer simplement... J'essaye, pour compléter mes recherches en LaTeX3, de créer une macro pour traiter une liste d'éléments et d'accéder à ses éléments. La commande de lecture peut spécifier un séparateur personnalisé, et la commande d'accès peut afficher ou stocker. Là où j'ai été confronté à un souci que je n'imaginais pas, c'est la gestion des éléments de la liste, que je dois pouvoir donner sous forme brute, ou sous forme d'une macro (latex2 ou latex3), et là je n'arrive pas à gérer les possibilités, je dois spécifier (version étoilée) que je travaille avec l'une ou l'autre des capacités... Mon code est le suivant : \documentclass{article} \usepackage{amsmath} \ExplSyntaxOn \NewDocumentCommand\pflcreatelistsingle{ s O{,} m m } { % #1 = étoilé => mode argument, sinon mode macro (à voir :-/) % #2 = séparateur principal (par défaut: ,) % #3 = nom de la structure (ex: maliste) % #4 = contenu de la liste % Stocker le séparateur principal \tl_if_exist:cF { g__pfl_#3_mainsep_tl } { \tl_new:c { g__pfl_#3_mainsep_tl } } \tl_gset:cn { g__pfl_#3_mainsep_tl } { #2 } %liste à construire \seq_if_exist:cF { g__pfl_#3_main_seq } { \seq_new:c { g__pfl_#3_main_seq } } \seq_clear:c { g__pfl_#3_main_seq } %gestion arg/macro ? \IfBooleanTF{#1} { %expansion de la liste, si besoin \tl_set:Nn \l_tmpmylist_tl { #4 } \seq_set_split:NnV \l_tmpa_seq { #2 } { \l_tmpmylist_tl } } { \seq_set_split:NnV \l_tmpa_seq { #2 } { #4 } } % Toujours utiliser une seq, même pour les virgules \seq_gset_eq:cN { g__pfl_#3_main_seq } \l_tmpa_seq % Stocker le nombre d'éléments \int_if_exist:cF { g__pfl_#3_count_int } { \int_new:c { g__pfl_#3_count_int } } \int_gset:cn { g__pfl_#3_count_int } { \seq_count:c { g__pfl_#3_main_seq } } } \NewDocumentCommand\pflgetfromlistsingle{ s m m O{\myelt} } { % #2 = nom, #3 = index, #4 = macro \int_set:Nn \l_tmpa_int { \int_eval:n { #3 } } \tl_clear:N \l_tmpa_tl \tl_set:Nx \l_tmpa_tl { \seq_item:cn { g__pfl_#2_main_seq } { \int_use:N \l_tmpa_int } } \IfBooleanTF{#1} { \tl_if_exist:NF \g__pfleltlistsingle_result_tl { \tl_new:N \g__pfleltlistsingle_result_tl } \tl_gset_eq:NN \g__pfleltlistsingle_result_tl \l_tmpa_tl \tl_use:N \l_tmpa_tl } { \tl_set_eq:NN #4 \l_tmpa_tl } } \ExplSyntaxOff \begin{document} %si argument en 'dur', version non étoilée fonctionne \pflcreatelistsingle{maliste}{ {1+\dfrac{1}{x}} , { \sqrt{x+61} } } Élément n°1 : $\pflgetfromlistsingle*{maliste}{1}$\\ Élément n°2 : \pflgetfromlistsingle{maliste}{2}[\myelt]$\myelt$\\ Élément n°3 : $\pflgetfromlistsingle*{maliste}{3}$ %si argument macro, version non étoilée fonctionne \def\maliste{ {1+\dfrac{1}{x}} , { \sqrt{x+61} } } \pflcreatelistsingle{maliste}{ \maliste } Élément n°1 : $\pflgetfromlistsingle*{maliste}{1}$\\ Élément n°2 : \pflgetfromlistsingle{maliste}{2}[\myelt]$\myelt$ %si argument en dur avec imbrication, version étoilée obligatoire \pflcreatelistsingle*{maliste}{ AAA , { BBB,CCC } } Élément n°1 : $\pflgetfromlistsingle*{maliste}{1}$\\ Élément n°2 : \pflgetfromlistsingle{maliste}{2}[\myelt]$\myelt$ \end{document} J'ai globalement compris le fonctionnement de l'expansion en latex3, mais j'ai l'impression que l'interaction latex2/latex3 est moins explicite que je l'aurais envisagé... |
Supposons que l'on a exécuté :
\def\blabla{un,deux,trois}. On applique ensuite\pflcreatelistsingle{maliste}{\blabla}. Comment LaTeX pourra-t-il savoir si la liste à stocker dansmalisteest une liste de longueur 1 (avec comme unique composante\blabla) ou bien une liste de longueur 3 (avec comme composantesun,deuxettrois) ? Il faut donc bien deux syntaxes.Pour préciser un peu, et après quelques tests supplémentaires, j'ai constaté que le traitement de mon argument (en brut ou via une macro) était différent : 1/ suivant la présence ou non du séparateur dans les éléments e1 , e2 , e3 , ... 2/ suivant ou non l'utilsation d'une macro comme argument
Je pensais que la gestion des arguments dans des macros l3 pourrait être transparente, mais je me rends compte que pour des cas particuliers (tordus ?) cela n'est pas aussi simple :-)
Pour préciser un peu, il semblerait que le fait de protéger les éléments d'une liste par des accolades puisse aider
La plupart des langages de programmation classiques s'appuient sur un processus d'évaluation des expressions et, en particulier, d'évaluation des arguments d'une fonction avant application de la fonction elle-même. Mais TeX ne propose rien d'équivalent. L'expansion au sens de TeX n'est pas une évaluation mais une macro-expansion (comme le système de macros du précompilateur C).
Dans le cas présent, le moyen de se rapprocher le plus d'une évaluation classique serait de protéger les éléments des listes avec des
\exp_not:n {...}puis de faire une expansion complète (de typee) de l'argument de la macro.J'ai 'réussi' (je mets des guillemets car je pense que ça va soulever d'autres soucis...) en utilisant une expansion de type 'o' (avec la variante créée), ce qui semble à la fois gérer les arguments classiques et les arguments type macro.... Mais je me doute que mes travaux et avancées sont sur une base fragile :-)