# Can one modifiy an argument within its macro?

I wish to give a default value to a series of arguments when they are empty. I could make a test prior the use of the argument and modify the value just before each of the usage. I could even make a macro to do so. I could build a macro that encapsulate the initial macro that would "process" the arguments. A more elegant way would be to modify the argument, right at the beginning of the macro. Is it possible ?

I wish I could change the value in #1, something like \def#1{...}:

\def\DisplayNumber#1{
\def#1{\ifx&#1& 0\else#1\fi} % if argument empty, make #1 equal to 0
Result is : #1}

• Could you also provide the community with your use-case via a minimal example? Something tangible that highlights what you mean by "modify [a] macro argument"? – Werner Jun 15 '15 at 7:09
• @egreg : Thanks for editing, I tried to do that with {} (code sample) but had not the result awaited (instead, I lost the carriage returns). – user1771398 Jun 15 '15 at 7:35

The simplest way is adding the conditional at the point of use:

\def\DisplayNumber#1{%
Result is: \ifx&#1&0\else#1\fi
}


Instead of the \ifx&#1& test for emptyness, you can use

\if\relax\detokenize{#1}\relax


provided you have e-TeX extensions enabled.

You can also define a utility macro:

\def\printifempty#1#2{\ifx&#2&#1\else#2\fi}


\def\DisplayNumber#1{%
Result is: \printifempty{0}{#1}%
}


A “generic” strategy for changing arguments is to define an “external” and an “internal” macro. With the help of expl3 one can avoid cumbersome code with scores of \expandafter and \romannumeral.

\input expl3-generic

\ExplSyntaxOn

\cs_new:Nn \test_internal_macro:nnnnnn
{
\internalmacro{#1}{#2}{#3}{#4}{#5}{#6}
}
\cs_generate_variant:Nn \test_internal_macro:nnnnnn { ffffff }

\cs_new:Nn \test_external_macro:nnnnnn
{
\test_internal_macro:ffffff
{ \tl_if_blank:nTF { #1 } { 0 } { #1 } }
{ \tl_if_blank:nTF { #2 } { 0 } { #2 } }
{ \tl_if_blank:nTF { #3 } { 0 } { #3 } }
{ \tl_if_blank:nTF { #4 } { 0 } { #4 } }
{ \tl_if_blank:nTF { #5 } { 0 } { #5 } }
{ \tl_if_blank:nTF { #6 } { 0 } { #6 } }
}

\cs_new_eq:NN \externalmacro \test_external_macro:nnnnnn

\ExplSyntaxOff

\def\internalmacro#1#2#3#4#5#6{%
\bigskip Calling {\tt\string\externalmacro}\par
This is arg \#1: #1\par
This is arg \#2: #2\par
This is arg \#3: #3\par
This is arg \#4: #4\par
This is arg \#5: #5\par
This is arg \#6: #6\par
}

\externalmacro{A}{B}{C}{D}{E}{F}

\externalmacro{A}{}{}{D}{E}{F}

\externalmacro{}{}{}{}{}{}

\bye


The \externalmacro command is defined to call \internalmacro with “normalized” arguments: if one of them is blank, 0 is substituted.

This calls \test_internal_macro:ffffff, which is a wrapper around \internalmacro that's the one you give the “real” definition.

• Sure, as I mentioned in the question, these are ways to do it. But, that's the problem with the very minimal, I have several usage of the argument. I wish something more "elegant", more readable also at the point of usage of the argument. – user1771398 Jun 15 '15 at 7:39
• @user1771398, store the value in a macro, and do the test at the storing stage. – daleif Jun 15 '15 at 7:45
• @daleif interesting idea : it means in fact a transfer to another set of "variables", let say \a,\b... It is very near from the encapsulation alternative, but with other names than #1,#2 etc. – user1771398 Jun 15 '15 at 7:52
• @user1771398 another benefit is that you can use these in the end part of a normal \newenvironment definition. There env args does not apply (can be done using xparse). Also see the etoolbox package for various useful macroing tools. – daleif Jun 15 '15 at 8:13
• @user1771398 What's the problem with \printifempty? I'd avoid doing \def inside the replacement text of \DisplayNumber if expandable alternatives are available. – egreg Jun 15 '15 at 8:47