recursive list type like definition in LaTeX
Here is an alternative solution which does not need to iterate the list twice. After the first element, the \do
is replaced by \mydo
:
\documentclass{article}
\usepackage{etoolbox}
\newcommand*{\mydo}[1]{;\,#1}
\newcommand{\mylist}[1]{%
\renewcommand*{\do}[1]{##1\let\do\mydo}%
\left[\docsvlist{#1}\right]% Process list
}
\begin{document}
$\mylist{aa,bb,cc}$
$\mylist{aa}$
\end{document}
The character ;
must be shifted to be placed inside of the \ifnum\value....\fi
test.
I also added a much, much, much shorter expl3
version right before \begin{document}
, although the expl3
syntax might be very strange to L3 newbies...
I used the \docsvlist
and \forcsvlist
macros up to two years (2015) ago, but shifted then to he much more powerful expl3
syntax (although not easy to learn), especially for the multitude of lists there are in expl3
, such as seq
or clist
or prop
lists, which provide more functionality, in my point of view.
But first to the \ifnum...
test:
\ifnum\value{listcount} < \value{totalcount}
;\,
\fi
just tests whether the current value of the listcount
counter is smaller than the value of totalcount
counter and prints a ;\,
then, otherwise it doesn't.
The expl3
version is at the end and much simpler in its usage, no tests are needed (in fact, they are hidden behind \seq_use
).
First enter the expl3
- syntax style with \ExplSyntaxOn
and store the comma separated list values of the argument to a temporary sequence variable \l_tmpa_seq
. Later display this list with \seq_use:Nn \l_tmpa_seq {;\,}
-- the command takes care about the end of the list.
In order to prevent space gobbling, the wrapper command \displaylist
is defined outside, see also
Spaces in l3prop for the topic of spaces with expl3
.
\documentclass{article}
\usepackage{etoolbox}
\newcounter{listcount}
\newcounter{totalcount}%
\newcommand{\mylist}[1]{%
\setcounter{totalcount}{0}% Reset total count
\renewcommand*{\do}[1]{\stepcounter{totalcount}}% Reconfigure count
\docsvlist{#1}% Count number of items
\setcounter{listcount}{0}% Reset current item count
\renewcommand*{\do}[1]{% Reconfigure item \do
\stepcounter{listcount}% Next item
##1\ifnum\value{listcount}<\value{totalcount};\,\fi% Print item
}
\left[\docsvlist{#1}\right]% Process list
}
\begin{document}
$\mylist{aa,bb,cc}$
$\mylist{aa}$
\end{document}
Of course $\mylist{}$
will yield []
.
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\myotherlist}[1]{%
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\displaylist{\seq_use:Nn \l_tmpa_seq {;\,}}
}
\ExplSyntaxOff
\newcommand{\displaylist}[1]{%
\left[#1\right]%
}
\begin{document}
$\myotherlist{}$
$\myotherlist{aa,bb,cc}$
$\myotherlist{aa}$
\end{document}
A fully expandable version:
\documentclass{article}
\makeatletter
\newcommand{\ocamllist}[1]{\left[\ocaml@list#1,,\@nil}
\def\ocaml@list#1,#2,#3\@nil{%
\if\relax\detokenize{#2}\relax
\expandafter\@firstoftwo % no comma
\else
\expandafter\@secondoftwo
\fi
{\if\relax\detokenize{#1}\relax\,\else#1\fi\right]}
{#1;\ocaml@list#2,#3,\@nil}
}
\makeatother
\begin{document}
$\ocamllist{}$
$\ocamllist{aa}$
$\ocamllist{aa,bb}$
$\ocamllist{aa,bb,cc}$
\end{document}
Not expandable, but more compact:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\ocamllist}{m}
{
\left[
\clist_set:Nn \l_hongxu_ocamllist_clist {#1}
\clist_if_empty:NTF \l_hongxu_ocamllist_clist
{ \, }
{ \clist_use:Nn \l_hongxu_ocamllist_clist {;} }
\right]
}
\clist_new:N \l_hongxu_ocamllist_clist
\ExplSyntaxOff
\begin{document}
$\ocamllist{}$
$\ocamllist{aa}$
$\ocamllist{aa,bb}$
$\ocamllist{aa,bb,cc}$
\end{document}