Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Consider the following code:

I'm trying to write a \newcommand that will accept either m or n arguments, where m < n. Here m=4, n=6. I want to set things up so that if I call a newcommand, and it is passed 6 arguments, it will ignore the latter two if \fl is defined.

The rationale for this is that I want to merge different commands depending on different options, but I want to call the commands in the same way.

\documentclass{article}

\def\fl{}

\ifdefined\fl
  \newcommand{\xx}[4]
  {#1 #2 #3 #4}
\else
  \newcommand{\xx}[6]{%
    {#1 #2 #3 #4
      \begin{#5}
        \item foo
      \end{#6}
    }
  } \fi

\begin{document}
\xx{a}{b}{c}{d}{enumerate}{enumerate}
\end{document}

To be clear, I want to get

a b c d

if \fl is defined, and

a b c d
\begin{enumerate}
\item foo
\end{enumerate}

if it is not.

share|improve this question
    
In the true branch do \newcommand{\xx}[6]{#1 #2 #3 #4}; where's the problem? –  egreg Jun 4 at 21:12
    
@egreg I want to use the same code for both. –  Faheem Mitha Jun 4 at 21:12

4 Answers 4

up vote 5 down vote accepted

Nothing requires you use all arguments in the replacement text:

\documentclass{article}

\def\fl{}

\ifdefined\fl
  \newcommand{\xx}[6]
  {#1 #2 #3 #4}
\else
  \newcommand{\xx}[6]{%                                                                                                                                                    
    {#1 #2 #3 #4                                                                                                                                                           
      \begin{#5}                                                                                                                                                           
        \item foo                                                                                                                                                          
      \end{#6}                                                                                                                                                             
    }                                                                                                                                                                      
  } \fi

\begin{document}                                                                                                                              
\xx{a}{b}{c}{d}{enumerate}{enumerate}
\end{document}

Output when \fl is defined

enter image description here

Output when \fl is not defined

enter image description here

In order to get this, I just put % in front of \def\fl{}


If the status of \fl is changing in the document, a more complex strategy is necessary:

\documentclass{article}[12pt]

\makeatletter
\newcommand{\xx}[4]{%
  #1 #2 #3 #4%
  \ifdefined\fl
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\@gobbletwo}%
  {\xx@aux}%
}
\newcommand\xx@aux[2]{%
  \begin{#1}
    \item foo
  \end{#2}
}

\begin{document}
Here \verb+\fl+ is not defined

\xx{a}{b}{c}{d}{enumerate}{enumerate}

\bigskip
\newcommand{\fl}{}

Here \verb+\fl+ is defined

\xx{a}{b}{c}{d}{enumerate}{enumerate}

\end{document}

enter image description here

share|improve this answer

Here is a version that uses the xparse package to make parameters #5 and #6 optional.

If \fl is not defined, then we can process both a four parameter and a six parameter version, and report an error in case a 5 parameter version is encountered.

If \fl is defined, then we process a case of 4, 5, or 6 parameters as if it was a 4 parameter version.

enter image description here

Code:

\documentclass{article}
\usepackage{xparse}

\newcommand{\MyError}[3]{%
    Error: #1: #2 #3%
    %\PackageError{#1}{#2}{#3}% <-- Use this once code is debugged.
}%


\NewDocumentCommand{\xx}{m m m m g g}{%
    \ifdefined\fl
        % only the first four parameters are useful
        \xxFour{#1}{#2}{#3}{#4}%
    \else
        % Allow for 4 or 6 parameters
        \IfNoValueTF{#5}{%
            % #5 not provided, so default back to 4 parameter version
            \xxFour{#1}{#2}{#3}{#4}%
        }{%
            \IfNoValueTF{#6}{%
                % Only 5 parameters were provided
                \MyError{xx}{5 Parameters were provided. Required either 4 or 6 parameters since \textbackslash fl is not defined}{C}%
            }{%
                \xxSix{#1}{#2}{#3}{#4}{#5}{#6}%
            }%
        }%
    \fi
}%

\newcommand{\xxFour}[4]{%
    Four parameters: #1, #2, #3, #4
}%

\newcommand{\xxSix}[6]{%
    \begin{#5}
        \item Parameter 1: #1
        \item Parameter 2: #2
        \item Parameter 3: #3
        \item Parameter 4: #4
        \item Parameter 5: #5
        \item Parameter 6: #6
    \end{#6}
}%

\newcommand{\Test}{% so that we can repeat this 
\textbf{4 paramaters:}
\xx{a}{b}{c}{d}

\bigskip\par
\textbf{5 paramaters:}
\xx{a}{b}{c}{d}{enumerate}

\bigskip\par
\textbf{6 paramaters:}
\xx{a}{b}{c}{d}{enumerate}{enumerate}
}%

\begin{document}
\textbf{\textbackslash fl NOT defined}:

\Test

\bigskip\par
\def\fl{}
\textbf{\textbackslash fl defined}:

\Test

\end{document}
share|improve this answer

Here are some options (not extensively tested in your setup though):

Option A:

Define \xx to work on 4 or 6 arguments by peeking ahead and see whether a new group \bgroup is started.

enter image description here

\documentclass{article}

\makeatletter
\newcommand{\xx@}[2]{%
  #1 #2
}
\newcommand{\xx}[4]{%
  #1 #2 #3 #4
  \@ifnextchar\bgroup\xx@\relax
}
\makeatother

\begin{document}
\xx{a}{b}{c}{d}{enumerate}{enumerate}

\xx{a}{b}{c}{d}

\xx{a}{b}{c}{d}{enumerate}{enumerate}

\end{document}

This, of course, does not take \fl into consideration. In the above example, \xx@ would contain the environment definition, effectively designated to handle the two last arguments.

Option B:

Use it as you specified:

\documentclass{article}

\def\fl{}

\ifdefined\fl
  \newcommand{\xx}[4]{%
    #1 #2 #3 #4
  }
\else
  \newcommand{\xx}[6]{%
    #1 #2 #3 #4 #5 #6
  }
\fi

\begin{document}

\xx{a}{b}{c}{d}% or \xx{a}{b}{c}{d}{enumerate}{enumerate}

\end{document}
share|improve this answer
  • The following example tests for fl inside the definition of \xx.

  • Also it uses the more natural switch \iffl instead of testing, if a macro is defined.

  • The number of arguments is reduced to 5, because \begin{#5} and \end{#6} should not have different arguments.

Example:

\documentclass{article}

\newif\iffl

\newcommand{\xx}[5]{%
  #1 #2 #3 #4%
  \iffl
    \begin{#5}
      \item foo
    \end{#5}%
  \fi
}

\begin{document}
  \flfalse
  \subsection*{Case: flfalse}
  \xx{a}{b}{c}{d}{enumerate}

  \subsection*{Case: fltrue}
  \fltrue
  \xx{a}{b}{c}{d}{enumerate}
\end{document}

Result

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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