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!

  • This should be as easy as \newcommand{\foo}[1]{\left[ #1 \right]}, and then use \foo{a, b, c}. – Werner Apr 12 '21 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? :( – Fuzzy Lumpkins Apr 12 '21 at 19:35
  • So you want to do more work for the same output. Yes, that's possible. – Werner Apr 12 '21 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... – Fuzzy Lumpkins Apr 12 '21 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 '21 at 19:50
  • Yes. My apologies, I've updated the OP (just noticed after your reply that I forgot to add the backslashes). – Fuzzy Lumpkins Apr 12 '21 at 19:54

3 Answers3

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

egreg
  • 1,121,712
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.

Don Hosek
  • 14,078
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}

Werner
  • 603,163