# xparse empty arguments

I have defined a command using xparse as

\DeclareDocumentCommand\mymacro{o o o}


and I want to call it with various numbers of arguments (up to 3)

\mymacro, \mymacro[test][two], \mymacro[][][test]


etc...

The issue is that [] doesn't seem to return a \NoValue but an empty token as the tests I use \IfNoValueTF never return false on it.

Is there a way to make an "empty" argument like \mymacro[] set #1 to \NoValue when it is an empty string?

Essentially I need "empty" arguments to be set to \NoValue for my code to work.

I could always do

\mymacro[\NoValue][test][\NoValue]


but of course that defeats the purpose of making it simple.

In my code I use \IfNoValueTF{#n} a lot but for it to work on empty arguments I would need something like \IfNoValueOrEmptyTF.

-
Instead of three optional arguments you might want to consider using key-value pairs. –  egreg Jul 13 '12 at 19:15

Using a mixture of xparse and \ifx conditionals you can test for empty arguments:

\documentclass{article}
\usepackage{xparse}% http://ctan.org/pkg/xparse
\makeatletter
\DeclareDocumentCommand\mymacro{o o o}{
\def\@tempa{#1}Arg 1 is \ifx\@tempa\@empty\relax empty\else #1\fi. \par
\def\@tempa{#2}Arg 2 is \ifx\@tempa\@empty\relax empty\else #2\fi. \par
\def\@tempa{#3}Arg 3 is \ifx\@tempa\@empty\relax empty\else #3\fi.
}
\makeatother
\begin{document}
\verb|\mymacro|:\par\mymacro

\verb|\mymacro[test][two]|: \par\mymacro[test][two]

\verb|\mymacro[][][test]|: \par\mymacro[][][test]

\verb|\mymacro[][][]|: \par\mymacro[][][]

\verb|\mymacro[one][][three]|: \par\mymacro[one][][three]
\end{document}​

-
This worked. Wasn't fun changing the different syntaxes({} to \else\fi) it at least it works. I imagine one could wrap IfNoValue to include empty values easy enough though. –  AbstractDissonance Jul 13 '12 at 19:14
\makeatletter \newcommand{\IfNoValueOrEmptyTF}[3] {\IfNoValueTF{#1}{#2}{\def\@tempa{#1}\ifx\@tempa\@empty#2\else#3\fi}} \makeatother –  AbstractDissonance Jul 13 '12 at 19:18
\if\relax\detokenize{#1}\relax is more economic. –  egreg Jul 13 '12 at 19:19

Here is a \IfNoValueOrEmpty macro:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\IfNoValueOrEmptyTF}{mmm}
{
\IfNoValueTF{#1}{#2}
{
\tl_if_empty:nTF {#1} {#2} {#3}
}
}
\ExplSyntaxOff

\NewDocumentCommand{\mymacro}{ooo}{%
\IfNoValueOrEmptyTF{#1}{\typeout{\#1 is empty}}{\typeout{\string#1 is #1'}}%
\IfNoValueOrEmptyTF{#2}{\typeout{\#2 is empty}}{\typeout{\string#2 is #2'}}%
\IfNoValueOrEmptyTF{#3}{\typeout{\#3 is empty}}{\typeout{\string#3 is #3'}}%
}

\mymacro
\mymacro[a]
\mymacro[a][b]
\mymacro[a][b][c]
\mymacro[][b]
\mymacro[][][c]
\mymacro[][][]


However, a command with three optional arguments is difficult to manage, because one needs to remember which is which. A key-value syntax might be easier to employ.

-
Should this solution work with the current xparse version (2013/11/19)? I do get an empty document when trying to use this. –  Jörg Dec 9 '13 at 22:42
@Jörg This document is not supposed to produce output, but only messages on the terminal. –  egreg Dec 9 '13 at 22:49
Silly me, I missed the typeout... –  Jörg Dec 9 '13 at 22:56

Empty arguments and NoValue ones are not the same (and indeed using \NoValue directly is not supported as we will soon change the definition). Unlike LaTeX2e's \newcommand, xparse differentiates between an argument which is given but is empty and one which is not given. Thus if you want to be able to have input of the form

\foo[][][baz]


you don't want a NoValue test at all, but rather

\ExplSyntaxOn
\DeclareDocumentCommand{\foo}{ O{} O{} O{} }
{
\tl_if_empty:nTF {#1}
...
}


testing for an empty value using the code-level test. (We do not have a design-level empty test at the present time.)

-
Ok, that makes sense but I can't seem to get it to work using lualatex. I've tried including expl3 and things but it causes problems later on in some of my macros –  AbstractDissonance Jul 13 '12 at 18:56
@AbstractDissonance expl3 should not interfere with any code which does not use it. Could you give more detail? –  Joseph Wright Jul 13 '12 at 19:00
All I know is when I replaced If IfNoValueTF with tl_if_empty:NTF, added \ExplSyntaxOn and \usepackage{expl3} some of my lua code failed(saying some functions did not exist). Going to try werners method –  AbstractDissonance Jul 13 '12 at 19:06
@AbstractDissonance Did you use \tl_if_empty:NTF or \tl_if_empty:nTF - the two are distinct. I really would appreciate an example so I can check there is not an issue in epxl3: could you e-mail me what you saw (joseph.wright@morningstar2.co.uk)? –  Joseph Wright Jul 13 '12 at 19:12
@AbstractDissonance You said you added \ExplSyntaxOn, did you also include the corresponding \ExplSyntaxOff` after defining the command? –  Scott H. Jul 13 '12 at 19:48