# parse variable length comma separated list into command

I've been trying to modify the solution here into a LaTeX3 command that takes a variable length comma separated list of numbers and an optional argument (a unit) and prints the square root of the sum of the square of each number (along with the unit, if given).

\sumofsquares{2,3,-4}[m/s] should give

but \sumofsquares{3,-4}[m/s] should give

I've Googled for LaTeX3 examples but the ones I've found (documentation for xparse and expl3) don't contain any examples. The differences between lists and sequences mystifies me.

• A sequence is just a linear array of items. It has a first item, a second item and so on. To make one, you just take a list of things whose distinct elements are separated by some specific character, say ; and use \seq_set_split:Nnn {name}{separator}{list}. expl3 then provides functions for working with them. Think of a clist as a sequence whose separator is a comma. Functionally, I don't think there's much difference between them. sequence's are more versatile, clist's maybe shorten some syntax. – Scott H. Nov 11 '12 at 3:33
• A comma list is 'closer' to user syntax than a sequence: more convenient in many cases but not quite as general. As is mentioned in one of the answers, your input syntax is odd: I'd expect either \sumofsquares[m/s]{2,3,4} or \sumofsquares{2,3,4}{m/s} (with no optional argument). – Joseph Wright Nov 11 '12 at 8:35
• @Joesph The package I'm developing defines syntax the way one would say it. One always says units after the numerical value of a physical quantity. I can't see how or why it should be any other way. – user19024 Nov 12 '12 at 2:26

Here's an option using sequences, it could probably be made a little more compact as the code from the two helper macros is almost identical.

I'm not an expert so take my advice with a grain of salt but I would just stick with using sequences. They require an extra line of code here and there, but the additional options that they provide are well worth it.

\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\ExplSyntaxOn
\NewDocumentCommand{\sumofsquares}{ m o }
{
\IfNoValueTF {#2}
% if optional is missing call this
{\sum_of_squares:n {#1}}
% if not, then call this
{\sum_of_squares:nn {#1}{#2}}
}

\cs_new_protected:Npn \sum_of_squares:n #1
{
% does what the name suggests, set a sequence from the clist
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
% applies final arg to each element of second seq and stores result in first seq
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq {(##1)^2}
% \seq_use puts the items from the seq back in the input with "+" as a separator
\sqrt{\seq_use:Nnnn \l_tmpb_seq {+}{+}{+}}
}
\cs_new_protected:Npn \sum_of_squares:nn #1 #2
{
% same as above, but with the addition of units
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq {(\SI{##1}{#2})^2}
\sqrt{\seq_use:Nnnn \l_tmpb_seq {+}{+}{+}}
}

\ExplSyntaxOff
\begin{document}

$\sumofsquares{2,3,-4}$\par\medskip
$\sumofsquares{2,3,-4}[m/s]$

\end{document}


Here's a slightly shorter (and less clear) example using clists. The same method could have been used to shorten the code above.

\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\ExplSyntaxOn

\NewDocumentCommand{\sumofsquares}{ m O{} }
{
\sum_of_squares:nn {#1}{#2}
}

\cs_new_protected:Npn \sum_of_squares:nn #1 #2
{
\tl_if_empty:nTF {#2}
{
\clist_set:Nn \l_tmpa_clist {#1}
\sqrt{(\clist_use:Nnnn \l_tmpa_clist {)^2+(} {)^2+(} {)^2+(} )^2 }
}
{
\clist_set:Nn \l_tmpa_clist {#1}
\sqrt{(\clist_use:Nnnn \l_tmpa_clist {\,\si{#2})^2+(} {\,\si{#2})^2+(} {\,\si{#2})^2+(} \,\si{#2})^2}
}
}

\ExplSyntaxOff
\begin{document}

$\sumofsquares{2,3,-4}$\par\medskip
$\sumofsquares{2,3,-4}[m/s]$

\end{document}

• I think I'm taking LaTeX "programming" too literally. I have to remember that it's still a macro expansion markup. BTW, does the shorter solution allow for an arbitrary number of numerical arguments like the first solution? – user19024 Nov 12 '12 at 2:57
• Hi Joe: the second version also allows for an arbitrary number of arguments. They work the same, but because clists don't offer the equivalent of set_map, I used a workaround that happened to be a bit shorter. – Scott H. Nov 12 '12 at 3:25
• Why couldn't/shouldn't \sum_of_squares:nn be put within the braces of the \NewDocumentCommand code? Why is it needed as an intermediary in the first place? Programmatically, it looks like it shouldn't work as written. Obviously it does, but it still looks nonintuitive to me. – user19024 Nov 12 '12 at 16:12
• One more thing. Both version worked perfectly except when I used the first one with SIunits instead of siunitx. I kept getting "TeX capacity exceeded" errors when using any command defined in SIunits. I could define them myself locally and then they sometimes worked. The second example doesn't have this problem. – user19024 Nov 12 '12 at 16:17
• Re second comment: \seq_set_map:NNn requires an expandable third argument. Presumably, that is the issue with using SIunits rather than siunitx (see here for a comparison). The SIunits macros are defined with DeclareRobustCommand while the siunitx macros have protected definitions...the difference between the two is something that I'm not clear on. – Scott H. Nov 12 '12 at 18:32

Well, you can do this just with xparse, so

$\sumofsquares{2,3,-4}[m/s]$
$\sumofsquares{2,3,-4,4,7}$


yields:

## Code:

\documentclass{article}
\usepackage{siunitx}
\usepackage{xparse}
\usepackage{pgffor}

\newcommand{\SequenceOfSquares}{}
\newcommand*{\TermSeparator}{}%
\NewDocumentCommand{\sumofsquares}{m O{}}{%
\gdef\TermSeparator{}% clear up from last use (if any)
\def\Sequence{#1}
\foreach \x in  \Sequence {%
\xdef\SequenceOfSquares{\SequenceOfSquares \TermSeparator (\SI{\x}{#2})^2}%
\gdef\TermSeparator{+}%
}
\sqrt{\SequenceOfSquares}%
\gdef\SequenceOfSquares{}%
}

\begin{document}
$\sumofsquares{2,3,-4}[m/s]$

\medskip
$\sumofsquares{2,3,-4,4,7}$
\end{document}


Here is another solution. No need for xparse in this solution:

\documentclass{article}
\usepackage{siunitx}
\makeatletter
\newcommand\sumofsquares[2][]{%
\def\tempa{}%
\@for\reserved:=#2\do{%
\edef\tempa{\tempa\ifx\tempa\empty\else+\fi(\SI{\reserved}{#1})^2}%
}
\sqrt{\tempa}%
}
\makeatother
\begin{document}
$\sumofsquares[m/s]{2,3,-4}$
\par\medskip
$\sumofsquares{2,3,-4,4,7}$
\end{document}


# Putting the optional argument at the end

That is the OP's choice; I don't recommend it.

\documentclass{article}
\usepackage{siunitx}
\makeatletter
\newcommand*\sumofsquares[1]{\@testopt{\@sumofsquares{#1}}{}}
\def\@sumofsquares#1[#2]{%
\begingroup
\def\tempa{}%
\@for\reserved:=#1\do{%
\edef\tempa{\tempa\ifx\tempa\empty\else+\fi(\SI{\reserved}{#2})^2}%
}
\expandafter\endgroup\expandafter\sqrt\expandafter{\tempa}%
}
\makeatother
\begin{document}
$\sumofsquares{2,3,-4}[m/s]$
\par\medskip
$\sumofsquares{2,3,-4,4,7}$
\end{document}

• Ok, but the OP had requested that the optional parameter be the second parameter, not the first. Not saying that I think that that is a good idea. – Peter Grill Nov 11 '12 at 6:02
• That is easy to address. See the updated solution. – Ahmed Musa Nov 12 '12 at 18:40
• As I said in a previous comment, one always says/writes the unit after the numerical value, never the other way around. My target audience is students and instructors of physics and I want to encourage a "write what you think" model. It's far more intuitive. – user19024 Nov 12 '12 at 22:07