[Tex/LaTex] parse variable length comma separated list into command

comma-separated listlatex3macrosmath-mode

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

enter image description here

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

enter image description here

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.

Best Answer

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}