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.

I've been banging my head against this for days. I have a macro which takes a macro name and its arguments. It then re-arranges the arguments a bit and then calls the passed macro with the re-arranged arguments and so ends like this:

#1{\arga}{\argb}{\argc}

where arga ... \argc are the processed arguments. However. I need to have \arga ... \argc fully expanded before the macro stored in #1 is called. I cannot for the life of me work this out after days of playing with \expandafter, \noexpand, etextools etc. I can't use expl3 and I'd really prefer not to use etextools but etoolbox is available. Here is a MWE:

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  #1{\arga}{\argb}{\argc}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

This results in "\arga \argb \argc" but I want "arg1arg2arg3". \expandafter will do this in \x but not for three arguments in a row. etextools has some macros to do this but I really want to avoid it (it clashes with etoolbox in some ways and I must have etoolbox). I couldn't get the etextools macros to work even when I tried (\ExpandNextTwo etc.)

UPDATE: I realised that in my case, the args can contain robust macros like:

\documentclass{article}
\usepackage{etoolbox}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \edef\argb{\ifstrequal{#3}{arg2}{arg2}{}}%
  \def\argc{#4}%
  {\protected@edef\z{\noexpand#1{\arga}{\argb}{\argc}}\z}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

In which case (using egreg's answer as an example), it isn't fully expanded. As Joseph and egreg mention below, this isn't doable, you just have to use non-robust macros in such cases, for example. I'll let the question stand as it because it is informative.

share|improve this question
    
Is this your actual use-case? You want/need \detokenize? –  Werner Mar 27 '13 at 8:15
    
@Werner I think this is a very simplified case: the \defs here are clearly just to illustrate the point, as you don't actually need them in the minimised case :-) –  Joseph Wright Mar 27 '13 at 8:17
    
I don't need detokenize, it's just there for illustration, as Joseph says. –  PLK Mar 27 '13 at 9:25
    
Robust macros can't be fully expanded, at least not in the way expected. Almost always they are robust because inside something unexpandable happens (like an assignment). That means you can't get out of them the 'text' or whatever, so it's a was of time worrying! –  Joseph Wright Mar 27 '13 at 11:53

2 Answers 2

up vote 18 down vote accepted

The 'classical' approach is to use \expandafter

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1%
    \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
      {\expandafter\expandafter\expandafter\arga\expandafter\expandafter\expandafter}%
        \expandafter\expandafter\expandafter{\expandafter\argb\expandafter}\expandafter
          {\argc}}

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

where we need so many of them to expand arg3 then arg2 and finally arg1. (This is what is effectively wrapped up in expl3's \exp_args:Nooo).

The rule of the number of \expandafters we need is 2n - 1, where n is how many tokens we want to expand. So for one token somewhere ahead, we need just one \expandfafter in each place to be 'skipped', to expand two tokens (second one then the first one) we need three \expandafters, for three tokens (as in the current case) we need seven \expandafters, and so one. This is easiest to see if you write/print out a short second and cross off the commands as TeX would read them: you'll find everything works out.

With e-TeX available, we can use an \edef and \unexpanded:

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \begingroup
    \edef\x{%
      \endgroup
      \noexpand#1
        {\unexpanded\expandafter{\arga}}%
        {\unexpanded\expandafter{\argb}}%
        {\unexpanded\expandafter{\argc}}%
    }%
  \x
}    

\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

(You can do the same without e-TeX using a series of toks, but that gets a bit confusing so I'd not normally do it.)


The question says no expl3, but for contrast the approach using a minimium of the functions it provides would read

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\def\x#1#2#3#4{
  \def\arga{#2}
  \def\argb{#3}
  \def\argc{#4}
  \exp_args:Nooo#1\arga\argb\argc
}    
\ExplSyntaxOff
\def\y#1#2#3{\detokenize{#1#2#3}}

\x\y{arg1}{arg2}{arg3}

\end{document}

which is I hope a lot more readable. (I'd probably want to use \exp_args:NVVV as we are using 'value stored in a variable', but that function is not pre-defined so I've avoided it here.)

share|improve this answer
1  
Can you detail the rule you used to know how many \expandafters were needed in the classical approach? Thanks. –  cjorssen Mar 27 '13 at 8:33
    
Regarding the etex approach, I usually use \expandafter\unexpanded\expandafter{. So I don't need the first \expandafter? –  cjorssen Mar 27 '13 at 8:34
1  
Brilliant, thanks. I just couldn't face working out the infinite \expandafter mantra to do this. The etex trick is nice too. Since this is for biblatex, I don't think we want to use expl3 just yet, unfortunately ... –  PLK Mar 27 '13 at 8:36
1  
@cjorssen There was a question very early in the life of the site about this (where you can save unnecessary tokens). \unexpanded works in the same way as a toks, and the rule there is that TeX will expand until it finds the first brace. Very useful when you want to expand more than once: \unexpanded\expandafter\expandafter\expandafter{\expandafter\foo\baz}, etc. –  Joseph Wright Mar 27 '13 at 9:03
4  
+10 Good advertizement for LaTeX3 –  Yiannis Lazarides Mar 27 '13 at 9:17

If you really want the arguments to be fully expanded, then

\documentclass{article}
\begin{document}

\def\x#1#2#3#4{%
  \def\arga{#2}%
  \def\argb{#3}%
  \def\argc{#4}%
  \begingroup\edef\z{\endgroup\noexpand#1{\arga}{\argb}{\argc}}\z
}

\def\y#1#2#3{\detokenize{#1#2#3}}

\def\foo{This is foo}

\texttt{\x\y{arg1}{arg2}{arg3\foo}}

\end{document}

will result in printing

arg1arg2arg3This is foo

whereas the \expandafter based solutions would print

arg1arg2arg\foo
share|improve this answer
    
Probably should go with \protected@edef if you are going this way, I'd say –  Joseph Wright Mar 27 '13 at 8:58
    
@JosephWright It depends, of course, on what the arguments contain and what is to be done with them. –  egreg Mar 27 '13 at 9:25
    
Hmm, seems that robust macros in the args won't expand in such cases, see updated, MWE above. –  PLK Mar 27 '13 at 9:31
    
@PLK Robust macros such as \ifstrequal will never be expanded in a \edef; but also the \expandafter method would do essentially the same. –  egreg Mar 27 '13 at 10:40
    
I just realised this and so I found some non-robust ones which are better suited ... thanks. –  PLK Mar 27 '13 at 10:53

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.