4

From general programming languages, I'm used to calling functions in the following way:

myfunction(argument1, argument2, ..., argumentn)

It seems like latex requires this syntax

\mycommand{argument1}{argument2}...{argumentn}

to use commands. Can I call commands using the usual function syntax (instead of writing out braces for every single argument)? I want to be able to do this:

\mycommand{argument1, argument2, ..., argumentn}
  • Welcome to TeX.SX! If the command is defined that way, it is possible, but mostly not. – TeXnician Apr 16 '17 at 16:00
  • 3
    TeX syntax requires separate arguments, in general, not least because , is perfectly valid in general text. We can show you how to define commands that split input at commas, but that won't alter other pre-defined commands. Would that be an answer? – Joseph Wright Apr 16 '17 at 16:01
  • You're suggesting writing the command so that it splits the argument on commas (as if it were a string)? This is something that has to be programmed into the command and isn't built-in to the language? That's not really what I was looking for. – isthisreallife Apr 16 '17 at 16:07
  • it all depends on the command for example you can do \usepackage{array,color,longtable,booktabs} – David Carlisle Apr 16 '17 at 16:24
  • 1
    @isthisreallife: It always depends on the purpose of the macro whether the comma separated list or the {} delimited argument approach is useful. Otherwise you still have to say that the 17th element of the CSV-list should be typeset or processed further within the macro – user31729 Apr 16 '17 at 16:27
5

Other answers have dealt with how one can split at commas, but perhaps some wider explanation is also useful. It's important to start with the fact that whilst LaTeX can be programmed generally, it is a document preparation system for typesetting. The design of the underlying language (TeX) also reflects the same aim, and LaTeX largely uses the same conventions as TeX itself here.

In terms of passing arguments, TeX deals with 'balanced text', which is some arbitrary material (normally) starting with { and ending with }. The characters used to delimit the 'balanced text' can be altered, but not the fact that we need the two and that they are distinct. That means we have to pass arguments in the form

\foo{balanced text 1}{balanced text 2}

etc. TeX does allow a more complex 'delimited' argument type, so we can set up (as David as done) to split material at commas

\def\foo(#1,#2){Stuff with #1 and #2}
\foo(abc,def) => #1 = abc, #2 = def

but this has to be defined at the programming layer: we can't just 'switch the core syntax'. Moreover, the simple definition I've just used requires a comma in the input: if you are modelling on other general languages you are likely expecting the arguments to be optional. One can use more elaborate programming to split at variable numbers of commas, but this will always be a layer on top of the core.

One key point to bear in mind is that TeX doesn't have string data or a function/variable split: we have just 'tokens'. Importantly, this means that we might well expect a comma to be used anywhere, and so have to 'protect' commas if we use the \foo(abc,efg) syntax:

\foo({abc,def},ghi) => #1 = abc,def; #2 = ghi

which (to me) is no clearer than

\baz{abc,def}{ghi}

Also worth noting here is that using ( ... ) also carries some issues: they can't appear in the arguments without causing issues or without a more complex code set up (see xparse).

3

It is not always a good idea to force idioms from one language on to another but for example

enter image description here

\documentclass{article}
\def\zz#1{\zzz#1\relax}
\def\zzz#1,#2,#3,#4\relax{\fbox{#1} \fbox{#2} \fbox{#3} \fbox{#4}}
\begin{document}

\zz{a,b,c,d}

\end{document}

Note that unlike processing a comma separated list (as for example)

 \usepackage{array,color,longtable,booktabs}

the \zz(z) defined above has a fixed number of arguments, accessed as #1 to #4 but using a comma syntax rather than {}.

It also assumes the four arguments do not include , or \relax if they need to they need to be guarded by {} so \zz{{1,2},{3,4},{5,6},{7,8}}

3

An expl3 way (not using \SplitList from xparse directly) by defining the command and a processing command that does something with the elements of the argument list, but this processor command does basically do the same operation on the individual elements of the list.

Note: In case of many arguments that have different meanings, a key-value approach is more effective or at least less error prone.

\documentclass{article}

\usepackage{xparse}


\ExplSyntaxOn
\newcommand{\foocmd}[1]{%
  \seq_set_from_clist:Nn \l_tmpa_seq {#1}
  \seq_map_inline:Nn \l_tmpa_seq {%
    \fooprocessorcmd{##1}%
  }
}

\ExplSyntaxOn

\newcommand{\fooprocessorcmd}[1]{\fbox{#1}}

\begin{document}
\foocmd{r,o,f,y,b,i,v}
\end{document}
2

Here is a very simple listofitems approach.

\documentclass{article}
\usepackage{listofitems}
\newcommand\mycommand[1]{%
  \readlist*\myargs{#1}%
  The \myargslen{} arguments are \showitems\myargs.
  The 4th argument is ``\myargs[4].''
}
\begin{document}
\mycommand{this, is, a, big, test}

\mycommand{What, would, you do, for a, Klondike, bar?}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.