# Check number of arguments in a command

I know how to create if\else structures in LaTeX using \newif and \else. What I'm wondering is whether there's a way to check against the actual arguments given to a command. For example, if I have a command \newcommand{\mycomm}[3] and at call time I give it 2 (two) instead of 3 (three) arguments, I would like it to behave differently.

So far solutions I have found at SO have to do with determining emptiness or handling optional arguments; this is not quite what I want to do.

// Edit: What I need is something like the following:

\newcommand{\homeworkdata}[6]{
\begin{flushleft}
\noindent\makebox[\textwidth]{\LARGE \bf #1, #2 }
\Repeat{2}{\ \\}
\noindent\makebox[\textwidth]{\Large\bf  Homework \##3 }

\ \\
%  What I  need here is the option for the student to give me their first
and last name. If they do, I want their data to appear after "first & last name".
\noindent\makebox[\textwidth]{\large \bf  \textbf{First} \& \textbf{Last} Name:  \enspace \myline{4in}}
\Repeat{2}{\ \\ }
\noindent\makebox[\textwidth]{\large \bf  UID (9 digits): \enspace \myline{3in}}
\ \\
\end{flushleft}
\Repeat{2}{\ \\}


}

• So you want to circumvent TeX's input processing which would simply grab the next token as third argument? – TeXnician Sep 1 '18 at 17:08
• There will be three arguments, or an error at the TeX level: they might just not be what you expect! For example, \mycomm{a}{b} Then some stuff has arguments a, b and T. – Joseph Wright Sep 1 '18 at 17:08
• You can 'look ahead' for brace groups, if that is what you are after ... – Joseph Wright Sep 1 '18 at 17:09
• You could, with a trick, set up the syntax as \z{ }{ }[ ] where the 3rd argument (in brackets) is optional. Would that suit your needs? – Steven B. Segletes Sep 1 '18 at 17:16
• To further describe what I want to do, I want a command / environment that allows a student to write in their first and last name. If the student doesn't provide their first and last name, I only want it to say: "First and Last name" followed by a horizontal line. I am now editing the original post with what I need in detail. – Jason Sep 1 '18 at 17:20

2 possibilities

A

Here the 3rd argument is optional. Of course it requires bracket rather than brace syntax.

\documentclass{article}
\newcommand\z[2]{\def\zone{#1}\def\ztwo{#2}\zaux}
\newcommand\zaux[1][]{%
\ifx\relax#1\relax%
Two arguments: \zone{} and \ztwo%
\else%
Three arguments: \zone, \ztwo, and #1%
\fi
}
\begin{document}
\z{A}{B}

\z{A}{B}[C]
\end{document}


B

This allows a comma separated entry in the 2nd argument.

\documentclass{article}
\usepackage{listofitems}
\newcommand\z[2]{%
First argument: #1.\par
\ifnum\studentlen=1\relax%
Only one name provided: \student[1]%
\else%
Two names provided: \student[1] and \student[2]%
\fi%
}
\begin{document}
\z{A}{B}

\z{A}{B,C}
\end{document}


Are you aware that in TeX/LaTeX undelimited arguments consisting of a single token don't need to be nested in braces?

After defining \newcommand\foo[1]{This is argument 1: #1.},
\foo{b} will yield the same result as
\foo b.

After defining \newcommand\foo[2]{This is argument 1: #1. This is argument 2: #2.}, the following calls will all yield the same result:
\foo{a}{b}
\foo a{b}
\foo {a}b
\foo ab
\foo{a} {b}
\foo a {b}
\foo {a} b
\foo a b

This is because

1. you don't need braces when undelimited arguments consist of a single token.
2. (La)TeX does discard space tokens preceding undelimited arguments.

When called as \mycomm{a}{b}c—how shall \mycomm "know" whether the user intends to have c as \mycomm's third argument which consists of the single token c or whether the user intends to have \mycomm called with only two arguments, namely {a} and {b} while c shall not be considered a third argument?

The situation is ambiguous.

You can turn the situation into something unambiguous by having \mycomm process only one undelimited argument and having \mycomm check whether that argument in turn is of one of the patterns

{⟨argument 1⟩}

{⟨argument 1⟩}{⟨argument 2⟩}

{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}

...

{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}...{⟨argument k⟩}

and have \mycomm act accordingly in case one of these patterns is detected and have \mycomm delivering an error-message otherwise.

I.e.,

\mycomm{{⟨argument 1⟩}}

\mycomm{{⟨argument 1⟩}{⟨argument 2⟩}}

\mycomm{{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}}

...

\mycomm{{⟨argument 1⟩}{⟨argument 2⟩}{⟨argument 3⟩}...{⟨argument k⟩}}

Yesterday I answered a question similar to yours, subject: How to define a command with two optional arguments?, and provided an example for doing this with up to three arguments.

You can easily adapt that example, using the same strategy, for detecting up to nine arguments.

But in your scenario, where the situation is about users who might provide specific data, it may be better to have a key-value-interface, so that the user can pass the data she likes to pass via a comma-separated-key-value-list and thus is urged to specify by providing not only a value but the key also, what data she wishes to provide.

Something that the user can use like:

\homeworkdata[FirstName=Jason, LastName=Smith]{1}{2}{3}{4},
yielding that the name of the user is used.

\homeworkdata[LastName=Smith, FirstName=Jason]{1}{2}{3}{4},
yielding that the name of the user is used.

\homeworkdata{1}{2}{3}{4},
yielding that the defaults "First name" and "Last name" are used.

There are a lot of packages providing means for implementing key-val syntax:

https://ctan.org/topic/keyval

With these packages you can provide default-values which are used in case the user does not specify other values. For the key FirstName you could specify the default value First name and for the key LastName you could specify the defaule value Last name.