4

I am making a factory macro (A) that produces another macro (B). Macro B consists in affecting what it gets as parameters to variables when called. I am currently able to do all this without A, but this is not scalable, because it requires a lot of rewritting.

See Macro factory and argument passed at calling for the whole context.

Following the answers on question the previous question (Macro factory and argument passed at calling ) , I could make a new MWE with some points still opened :

  • point 1 : I put comas in the \clist_map_inline to artificially delimit each argument
  • point 2 : I put the list of the argument in the definition (the 3 m) : \NewDocumentCommand{\DefinitionVariables}{ m m m }%
  • point 3 : I put all the arguments in the \clist_map_inline function : \clist_map_inline:nn { #1, #2, #3}%

So the questions following these changes are :

  • point 1 : How can I, not have to put a comas ? I guess it has to do with the \clist_map_inline function, with coma being a built-in delimiter. It raises an issue when there is a coma inside an argument as the function will cut it as it considers it's a delimiter. I was thinking of having kind of a \foreach argument in {all the arguments}. Does such a thing exist ?
  • point 2 : How can I make this m dynamic ? By dynamic, I mean : sometimes, the function can take 3 arguments, but sometimes it can be 7 or 9 (between 1 and 9). Something like numberOfArgument * m
  • point 3 : It's related to the previous point, how can I also make this dynamic and not hard-coded ? (the \foreach argument in {all the arguments} would solve it).

    \documentclass[twoside]{article} % package pour utiliser une macro nested ac ses propres args \usepackage{xparse} \errorcontextlines32 \begin{document} %================================================================================== % Prerequisite : lines of code to define variableI to variableXVI %================================================================================== \iffalse \fi \newcommand{\DefinitVariable}[1]{% \expandafter\newcommand\csname variable\Roman{#1}\endcsname{}% }% % Loop for defining all the variable \newcounter{ctr} \loop \stepcounter{ctr} \expandafter\DefinitVariable{ctr}% \ifnum\thectr<16 \repeat %================================================================================== % Automation trial 5 : utilise la syntaxe expl3 \iftrue %\iffalse \ExplSyntaxOn \NewDocumentCommand{\DefinitionVariables}{ m m m }% <=== point 2 : there is as much 'm' as there is arguments { \int_zero:N \l_tmpa_int %\clist_map_inline:nn { #1 } \clist_map_inline:nn { #1, #2, #3}% <=== point 3 : allows not to put comas in the arguments, but rise the pb if there is comas inside the argument // { \int_incr:N \l_tmpa_int \tl_clear_new:c { variable \int_to_Roman:n { \l_tmpa_int } } \tl_set:cn { variable \int_to_Roman:n { \l_tmpa_int } } { ##1 } } } \ExplSyntaxOff \DefinitionVariables{Laetitia, 8 }{Pierre, 10}{Cedric}% <=== point 1 : coma inside the argument will be considered as a delimiter, so the mapping of variable will be wrong La variable 2 est : \variableII \\ FIN\\ La variable 1 est : \variableI \\ FIN\\ La variable 3 est : \variableIII \\ FIN\\ La variable 1 est : \variableI \\ FIN\\ \fi 

Any help is very appreciate !

7
  • I'm not sure what the expansion of \variableI should be. Should it be “Laetitia, 8”? Commented Apr 29, 2017 at 14:05
  • Yes, it should be the parameter passed. @egreg : I don't get why you are reformulating the call of \DefinitionVariables. The syntax is \DefinitionVariables{arg1}..{argX}..{argN} with X = 1 to X = N (N is 9 at max). Is this a latex rule ? Commented Apr 29, 2017 at 14:34
  • With passing a comma separated list (or anyhow delimited) you can override the limit of nine arguments. Commented Apr 29, 2017 at 14:41
  • Ah ok. Nice, but I still need to pass the arguments with the syntax of each argument being a real argument. I tried to put }{ as a delimiter, but an error is occuring. Commented Apr 29, 2017 at 14:54
  • Why should it be necessary to use the {...}{...} syntax? This limits you to nine arguments. Commented Apr 29, 2017 at 14:57

1 Answer 1

4

A development version of the previous code; the new \DefinitionVariables accepts two optional arguments, the fixed name and the delimiter; the latter is (almost) completely arbitrary, just choose a character (or combination thereof) that doesn't appear in the values you want to give the variables.

\documentclass{article} \usepackage{xparse} \ExplSyntaxOn \NewDocumentCommand{\DefinitionVariables}{O{variable}mO{,}} { \aline_df:nnn { #1 } { #2 } { #3 } } \int_new:N \l_aline_df_int \seq_new:N \l_aline_df_values_seq \cs_new_protected:Nn \aline_df:nnn { \int_zero:N \l_aline_df_int \seq_set_split:Nnn \l_aline_df_values_seq { #3 } { #2 } \seq_map_inline:Nn \l_aline_df_values_seq { \int_incr:N \l_aline_df_int \tl_clear_new:c { #1 \int_to_Roman:n { \l_aline_df_int } } \tl_set:cn { #1 \int_to_Roman:n { \l_aline_df_int } } { ##1 } } } \ExplSyntaxOff \begin{document} \DefinitionVariables{ Laetitia, 8; Patrick, 10; Cedric }[;] \noindent La variable 1 est : \variableI\\ La variable 2 est : \variableII\\ La variable 3 est : \variableIII\\ FIN \bigskip \DefinitionVariables[var]{A,B,C} \noindent La var 1 est : \varI\\ La var 2 est : \varII\\ La var 3 est : \varIII\\ FIN \end{document} 

enter image description here

A different routine based on a recursion for allowing the arguments to be delimited by braces. So long as an open brace follows, a new variable is defined.

\documentclass{article} \usepackage{xparse} \ExplSyntaxOn \NewDocumentCommand{\DefinitionVariables}{O{variable}} {% pass control to an inner function % #1 is the "name part", default "variable" \aline_df:n { #1 } } % define an integer variable \int_new:N \l_aline_df_int \cs_new_protected:Nn \aline_df:n { % the integer variable assigns the trailing roman number \int_zero:N \l_aline_df_int % start the recursion \__aline_df_peek:n { #1 } } \cs_new_protected:Nn \__aline_df_peek:n { % check whether the next token is { (ignoring spaces) \peek_catcode_ignore_spaces:NT \c_group_begin_token { % if it is, increment the counter and call % \__aline_df_next:nn { #1 } { #2 }, where % { #2 } is the next braced group \int_incr:N \l_aline_df_int \__aline_df_next:nn { #1 } } } \cs_new_protected:Nn \__aline_df_next:nn { % if the variable is already defined, clear it % otherwise create it \tl_clear_new:c { #1 \int_to_Roman:n { \l_aline_df_int } } % set the variable \tl_set:cn { #1 \int_to_Roman:n { \l_aline_df_int } } { #2 } % restart the recursion \__aline_df_peek:n { #1 } } \ExplSyntaxOff \begin{document} \DefinitionVariables{Laetitia, 8}{Patrick, 10}{Cedric} \noindent La variable 1 est : \variableI\\ La variable 2 est : \variableII\\ La variable 3 est : \variableIII\\ FIN \bigskip \DefinitionVariables[var]{A}{B}{C}{D}{E}{F}{G}{H}{I}{J}{K} \noindent La var 1 est : \varI\\ La var 2 est : \varII\\ La var 3 est : \varIII\\ La var 11 est : \varXI\\ FIN \end{document} 

enter image description here

3
  • Thx for the answer, this is definitely addressing point 2 and 3. Commented Apr 29, 2017 at 14:56
  • Fantastic !!! This is exactly what I needed ! I will put myself into expl3 and study it a bit more. Thx a lot @egreg for this answer and all the back and forth. Commented Apr 29, 2017 at 16:18
  • @Aline I added some comments to the code Commented Apr 29, 2017 at 16:25

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.