# How can I use one argument as the default value for another?

I'd like to define a command that takes 1, 2 or 3 arguments, and where the 2nd gets the same value as the 1st if it is not defined. I tried

\newcommand\codefrom[3][#1][Matlab]{ ... }


but I get an error saying

! Illegal parameter number in definition of \codefrom.
1
l.57 \newcommand{\codefrom}[3][#1][
Matlab]

Is there any way to accomplish what I want to do?

-
Sheesh, three answers in thirty seconds. Nice question, Tomas. –  Ryan Reich Nov 11 '10 at 9:55


\documentclass[12pt]{report}
\newcommand\storefirst{}
\newcommand\storesecond{}
\newcommand\codefromii[1][Matlab]{\storefirst, \storesecond, #1}
\begin{document}
\codefrom{first}\par
\codefrom{first}[second]\par
\codefrom{first}[second][third]
\end{document}

-
Brilliant! This works exactly as I want it to, and is simple enough to understand =) Thanks! –  Tomas Lycken Nov 11 '10 at 10:27

The question is old, but as all answers are unnecessary complicated, I want to provide a simpler solution using xparse's possibilities directly.

\documentclass{minimal}
\usepackage{xparse}
\begin{document}
\NewDocumentCommand{\codefrom}{mO{#1}O{Matlab}}{#1, #2, #3}
\end{document}


The result is . The first argument is mandatory, the second and third ones are Optional. The second argument's default value is the first argument, the third argument's default value is Matlab.

-

Here is a solution based on xparse:

\documentclass{minimal}

\usepackage{xparse}

\NewDocumentCommand\codefrom{moO{Matlab}}{%
\IfValueTF{#2}{%
\codefromaux{#1}{#2}{#3}%
}{%
\codefromaux{#1}{#1}{#3}%
}%
}
\NewDocumentCommand\codefromaux{mmm}{%
1 = #1, 2 = #2, 3 = #3%
}

\begin{document}

\codefrom{a}\par
\codefrom{a}[b]\par
\codefrom{a}[b][c]

\end{document}

-
Very interesting. Could you elaborate a bit on the moO? (I think I can guess what it means, but still some confirmation would be great.) –  Hendrik Vogt Nov 11 '10 at 13:50
m = mandatory argument, o = optional argument (square brackets) with no default value, O = optional argument (square brackets) with default value as given. There was recently a question about trying to be able to use the value of one argument directly as the default for a second in xparse: currently, I've not come up with a good way to do it, I'm afraid. –  Joseph Wright Nov 11 '10 at 13:57
\documentclass{article}
\makeatletter
\newcommand{\codefrom}[1][]{\def\c@defr@m{#1}\c@defrom}
\newcommand{\c@defrom}[2][\c@defr@m]{\message{[\c@defr@m,#1,#2]}}
\makeatother
\begin{document}
\codefrom{a}
\codefrom[a]{b}
\codefrom[a][b]{c}
\end{document}


Edit: An alternative, if it is important for you to access the parameters as #1–#3:

\newcommand{\codefrom}[1][]{\def\c@defr@m{#1}\c@defrom}
\newcommand{\c@defrom}[1][\c@defr@m]
{\expandafter\@codefrom\expandafter{\c@defr@m}{#1}}
\newcommand{\@codefrom}[3]{\message{[#1,#2,#3]}}

-
This is great, and almost what I need =) The output now shows [,,a] [a,a,b] [a,b,c], but I'd like it to be [a,a,a] [a,a,b] [a,b,c] (or with some permutation of it). Also, I don't see where the \c@defr@om command comes from, but your MWE compiles on my machine... –  Tomas Lycken Nov 11 '10 at 10:19
What \c@defr@om command? I neither use nor define one. I admit these names are hard to read and keep apart, though. I guess I have been badly influenced by lots of other (La)TeX code that uses the s@me s@rt of n@ming convention. Anyway, having #3 be the default value of #1 and #2 was not in your original specification. I don't have the time right now to come up with a good way to do that, but it is probably most easily achieved in a final processing step – if you're happy with a solution that treats [] the same way as if the optional parameter had been skipped. –  Harald Hanche-Olsen Nov 11 '10 at 12:09
+1 for the idea to use repeated \newcommand s. –  Hendrik Vogt Nov 11 '10 at 16:39

Yes, but you have to "roll your own", so to speak. (You should note that even the sort of optional arguments you see in various core LaTeX macros, like the ones which take two optionals, are not supported by the \newcommand syntax).

The basic mechanism is to use \@ifnextchar to figure out whether there is an optional argument, filling it in if not, and then calling an internal macro which doesn't take an optional argument. In your case the following seems reasonable (note: written on the fly):

\makeatletter
\newcommand{\codefrom}[1]{
\@ifnextchar[
{\codefrom@firstinner{#1}}
{\codefrom@firstinner{#1}[#1]}
}

\def\codefrom@firstinner#1[#2]{
\@ifnextchar[
{\codefrom@secondinner{#1}{#2}}
{\codefrom@secondinner{#1}{#2}[Matlab]}
}

\def\codefrom@secondinner#1#2[#3]{
...
}
\makeatother


As you can see, at each step it checks for a [ and, if it is not present, fills in the argument with the desired default. The last step has all the arguments, and continues the process.

-