# \def variables with xparse and other questions about variables

I'm writing a documentation for a REST API. So there's very much information that has to get repeated. So I'm trying to figure out a few things:

1. Consider the following code:

\newcommand\insertitem[1]{\item \texttt{#1}}

\NewDocumentCommand{\listfields}{ >{ \SplitList {,} } m }
{
\paragraph{General available fields:}
\begin{itemize}
\ProcessList{#1}{ \insertitem }
\end{itemize}
}

% works:
\listfields{a,b,c,d,e}

% doesn't work:
\def \fields {a,b,c,d,e}
\listfields{\fields}


It returns the whole set as a single string, so it's not iterating over it. Why? Or: How can I get it working?

2. To make the document more easy to maintain, I'd like to set 3 variables and use it in different ways. First the 3 variables:

% route
\def \route {/myRestRoute}

% fields
\def \fields {a,b,c,d,e}

% field descriptions
\def \fielddesc
{
description for a,
description for b,
description for c,
description for d,
description for e
}


Now (if problem 1. gets solved), I'd like to do the following: Output tuples of \field and \fielddesc. I'd have to process two lists at once for that somehow. The result should then look like:

\texttt{a} - description for a
\texttt{b} - description for b
\texttt{c} - description for c
\texttt{d} - description for d
\texttt{e} - description for e

3. Last but not least, I need to take 2 values from the \fields variable and use it as parameter for a function. And I need somehow to specify which 2 values it should take. By default value 2 and 3 is fine, but maybe I have to use values 1 and 4 sometime (at the moment this exception doesn't exist, but it's always better to be prepared):

\newcommand{\arf}[2]
{
#1, #2
}

% and call it using something like this:
\arf{\fields[1]}{\fields[2]}
% where [1] and [2] should be indices of the comma separated fields array.

-

## migrated from stackoverflow.comMar 5 '13 at 20:15

This question came from our site for professional and enthusiast programmers.

Welcome to TeX.sx! Your post was migrated here from Stack Overflow. Please register on this site, too, and make sure that both accounts are associated with each other (by using the same OpenID), otherwise you won't be able to comment on or accept answers or edit your question. –  Werner Mar 5 '13 at 20:23

What you want is not generally feasible with only xparse. The main problem in passing either an explicit list or a control sequence is in doing an expansion of the argument, which can go wrong if the list is explicit and the first item is a control sequence or anyway starts with one.

So it's better to separate the two cases and I propose a syntax such as

\listfields*{a,b,c,d,e}
\listfields{\fields}


so the * announces an explicit list. It's quite easy to add also an optional argument for changing the delimiter, that you'll see in action in the example code. So you can do

\listfields*[;]{a;b;c;d;e}
\listfields[;]{\fieldssemicolon} % \fieldssemicolon has ; as separator

\listdescriptions{\fields}{\fieldsdesc}
\listdescriptions[;]{\fieldssemicolon}{\fielddescsemicolon} % both use ;

\listdescription[;][,]{\fieldssemicolon}{\fieldsdesc}
\listdescription[,][;]{\fields}{\fielddescsemicolon}


For the "double mapping" I assume that both the fields and the descriptions are stored in macros and the same for \arf that uses the syntax

\arf{\fields}{2,3}
\arf[;]{\fieldssemicolon}{1,2}


# The example

\documentclass{article}
\usepackage{xparse}

\newcommand\insertitem[1]{\item \texttt{#1}}

\ExplSyntaxOn
\NewDocumentCommand{\listfields}{sO{,}m}
{
\paragraph{General~available~fields:}
\begin{itemize}
\IfBooleanTF{#1}
{\benj_listfields:nn {#2}{#3}}
{\benj_listfields:no {#2}{#3}}
\end{itemize}
}

\cs_new_protected:Npn \benj_listfields:nn #1 #2
{
\seq_set_split:Nnn \l_benj_fields_seq { #1 } { #2 }
\seq_map_inline:Nn \l_benj_fields_seq { \insertitem{##1} }
}
\cs_generate_variant:Nn \benj_listfields:nn { no }

\NewDocumentCommand{\listdescriptions}{O{,}omm}
{
\paragraph{General~available~fields~with~descriptions:}
\begin{itemize}
\IfNoValueTF{#2}
{\benj_list_descriptions:nnNN {#1} {#1} #3 #4}
{\benj_list_descriptions:nnNN {#1} {#2} #3 #4}
\end{itemize}
}
\cs_new_protected:Npn \benj_list_descriptions:nnNN #1 #2 #3 #4
{
\seq_set_split:NnV \l_benj_fields_seq { #1 } #3
\seq_set_split:NnV \l_benj_descriptions_seq { #2 } #4
\l_benj_fields_seq
\l_benj_descriptions_seq
\benj_make_description:nn
}
\cs_new_protected:Npn \benj_make_description:nn #1 #2
{
\item \texttt{#1},~#2
}

\NewDocumentCommand{\arf}{O{,}mm}
{% #1 (optional) = separator, #2 = list macro, #3 = list of items
\benj_arf:nNn {#1} #2 {#3}
}
\cs_new_protected:Npn \benj_arf:nNn #1 #2 #3
{
\paragraph{Some~fields:}
\begin{itemize}
\seq_set_split:NnV \l_benj_fields_seq { #1 } { #2 }
\clist_map_inline:nn { #3 } { \item \seq_item:Nn \l_benj_fields_seq { ##1 } }
\end{itemize}
}
\seq_new:N \l_benj_fields_seq
\seq_new:N \l_benj_descriptions_seq

\ExplSyntaxOff

\begin{document}
\section{List fields}
\listfields*{a,b,c,d,e}

\def \fields {a,b,c,d,e}
\listfields{\fields}

\def\fieldssemicolon{a;b;c;d;e}
\listfields[;]{\fieldssemicolon}

\newpage

\section{List fields with descriptions}
\def \fielddesc
{
description for a,
description for b,
description for c,
description for d,
description for e
}
\def\fielddescsemicolon
{
description for a;
description for b;
description for c;
description for d;
description for e
}

\listdescriptions{\fields}{\fielddesc}

\listdescriptions[;][,]{\fieldssemicolon}{\fielddesc}

\listdescriptions[;]{\fieldssemicolon}{\fielddescsemicolon}

\newpage
\section{Extract fields}
\arf{\fields}{2,3}

\arf{\fields}{1,3,5}

\arf[;]{\fieldssemicolon}{2,4}
\end{document}


-