1

I want to make a newcommand that can take any number of arguments, and concatenate them. For example \foo{a}{b}{c} Will give me \left[a,\ b,\ c\right], but should work for any number of variables and not just 3.

Thanks!

6
  • This should be as easy as \newcommand{\foo}[1]{\left[ #1 \right]}, and then use \foo{a, b, c}.
    – Werner
    Apr 12, 2021 at 19:32
  • This is a possible workaround I guess, but I'd still like to make it using the arguments rather than inserting the comma list every time. Is it not possible? :( Apr 12, 2021 at 19:35
  • So you want to do more work for the same output. Yes, that's possible.
    – Werner
    Apr 12, 2021 at 19:41
  • This should eventually be inserted into a math environment, so I prefer to not have to do the "backslash space" every time and wonder whether I've missed one... Apr 12, 2021 at 19:47
  • I don't understand. Are you inserting "backslash space" with every comma? As in, \foo{a, b, c} should output \left[ a,\ b,\ c \right] instead?
    – Werner
    Apr 12, 2021 at 19:50

3 Answers 3

2

I strongly believe that a syntax such as \foo{a,b,c} is much easier than the proposed \foo{a}{b}{c}, particularly when you have more than three items.

You just need to transform the input to get what you're looking for and this is a job for TeX.

There are several ways to do it, from cooking one for the task at hand to using predefined tools.

I wouldn't use “backslash-space” that adds too wide a space, but that's your choice and you can just replace the \, in the code below with “backslash space”.

\documentclass{article}
\usepackage{mathtools} % for \DeclarePairedDelimiterX

\ExplSyntaxOn
\DeclarePairedDelimiterX{\foo}[1]{[}{]}
 {    
  \fuzzylumpkins_foo:n { #1 }
 }

\clist_new:N \l__fuzzylumpkins_foo_clist

\cs_new_protected:Nn \fuzzylumpkins_foo:n
 {
  \clist_set:Nn \l__fuzzylumpkins_foo_clist { #1 }
  \clist_use:Nn \l__fuzzylumpkins_foo_clist { ,\, }
 }
\ExplSyntaxOff

\begin{document}

$\foo{a,b,c}$ $\foo[\big]{a,b,c,d,e,f}$

\bigskip

$\foo*{\dfrac{1}{2},\sqrt{2},x-y}$

\bigskip

$\displaystyle\foo[\bigg]{\sum_{k}a_k,\int f(x)\,dx}$
$\displaystyle\foo*{\sum_{k}a_k,\int f(x)\,dx}$

\end{document}

Note that I avoid adding \left and \right, because it doesn't really do what you think. It's better to specify the size manually like in the second example and resort to automatic sizing only when it's really necessary.

Compare the fourth and fifth examples, where I believe that the fourth one looks much better.

enter image description here

1

“All things are lawful, but not all things are profitable.” 1 Corinthians 10:23

This would be a weird syntax, but it's certainly doable: What you want to do is look at the next character and see if it's a { and if so, we grab an argument, otherwise, we close the list.

Here's some untested code:

\makeatletter
\def\foo#1{\left[#1\next@foo}
\def\continue@foo#1{
  ,#1\next@foo
}
\def\next@foo{\@ifnextchar\bgroup\continue@foo\@endfoo}
\def\end@foo{\right]}
\makeatother

this will requre all arguments (except the first) to be enclosed in braces.

1

It seems easier to pass the list using a single argument list-like format. Here is an implementation using etoolbox's list processing capabilities:

enter image description here

\documentclass{article}

\usepackage{etoolbox}

% https://tex.stackexchange.com/a/89187/5764
\newcommand{\foo}[2][,\ ]{%
  \def\itemdelim{\def\itemdelim{#1}}% Item delimiter delayed by one cycle
  \renewcommand*{\do}[1]{\itemdelim##1}% How each item is processed
  \left[\docsvlist{#2}\right]}% Process CSV list

\begin{document}

$\left[ a, b, c \right]$

$\left[ a,\ b,\ c \right]$

$\foo{a, b, c}$

$\foo{a,b,c}$

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .