# Macro factory and argument passed at calling (part 2)

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 !

• I'm not sure what the expansion of \variableI should be. Should it be “Laetitia, 8”? – egreg Apr 29 '17 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 ? – Aline Apr 29 '17 at 14:34
• With passing a comma separated list (or anyhow delimited) you can override the limit of nine arguments. – egreg Apr 29 '17 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. – Aline Apr 29 '17 at 14:54
• Why should it be necessary to use the {...}{...} syntax? This limits you to nine arguments. – egreg Apr 29 '17 at 14:57

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}


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}


• Thx for the answer, this is definitely addressing point 2 and 3. – Aline Apr 29 '17 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. – Aline Apr 29 '17 at 16:18
• @Aline I added some comments to the code – egreg Apr 29 '17 at 16:25