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 have defined a stack structure (I found an example in the LaTeX currfile package, which I adapted to my needs):

\def\MB@modulestack{}
\def\MB@modulestack@push#1{\xdef\MB@modulestack{{#1}\MB@modulestack}}
\def\MB@modulestack@top{\expandafter\MB@modulestack@top@eat\MB@modulestack\relax\relax}
\def\MB@modulestack@top@eat#1#2\relax{#1}
\def\MB@modulestack@pop{\expandafter\MB@modulestack@pop@eat\MB@modulestack\relax\relax}
\def\MB@modulestack@pop@eat#1#2\relax{\gdef\MB@modulestack{#2}}

I understand how it works, especially those \relax. I keep a 4-tuple of parameters there:

\def\MB@modulestack@push{{a}{b}{c}{d}}
\def\MB@modulestack@push{{1}{2}{3}{4}}

Now, to parse such a 4-tuple from the top of stack I wanted to use the following code:

\def\MB@modulestack@topitemparse@eat#1#2#3#4{... here I use #1, #2, #3, #4 ...}
\def\MB@modulestack@topitemparse{
  \expandafter\MB@modulestack@topitemparse@eat\MB@modulestack@top
}

...but it didn't work. While experimenting I found that I had to do this another way:

\def\MB@modulestack@topitemparse@eat#1#2#3#4#5\relax{... here I use  #1, #2, #3, #4 ...}
\def\MB@modulestack@topitemparse{
  \edef\MB@modulestack@topitem{\MB@modulestack@top}
  \expandafter\MB@modulestack@topitemparse@eat\MB@modulestack@topitem\relax\relax
}

Why does the first doesn't work and the second does? Why do I need to get #5 and \relax in the @eat macro? Why do I need to read the top of stack into variable, instead of passing it straight to the @eat macro?

share|improve this question
add comment

2 Answers

up vote 4 down vote accepted

This is the classic difference between a macro expansion language and an function-based system. When you do

\def\MB@modulestack@topitemparse{
  \expandafter\MB@modulestack@topitemparse@eat\MB@modulestack@top
}

you expand \MB@modulestack@top exactly once, which leaves TeX reading

\MB@modulestack@topitemparse@eat\expandafter\MB@modulestack@top@eat
  \MB@modulestack\relax\relax

which does not do what you want. You could work out the exact number of expansions needed to get this to work; in this case, you'd need:

\def\MB@modulestack@topitemparse{
  \expandafter\expandafter\expandafter
    \expandafter\expandafter\expandafter
    \expandafter\MB@modulestack@topitemparse@eat\MB@modulestack@top
}

which will expand everything as you want. However, this is clearly awkward, which is where \edef comes in as it always fully-expands stuff. The only danger is that the result of

\edef\MB@modulestack@topitem{\MB@modulestack@top}

might not be what you expect if the stack items are themselves expandable.

share|improve this answer
    
So \expandafter does only single level of expansion, not a full expansion I expected--like LISP's macroexpand-1, and not macroexpand. Thanks, that makes one thing clear. –  liori Apr 1 '11 at 15:44
    
@liori: No idea, I don't use LISP. The general point is that when you read carefully-written programming guides for TeX, each macro is always described as inserting <replacement text>, which is what happens at each expansion. So \expandafter does one expansion, replacing a macro by it's <replacement text>. –  Joseph Wright Apr 1 '11 at 15:50
    
@liori: I'm sure Lispers are crying their hearts out with the use of word macro in TeX. Macro in Lisp is a wholly different beast from the word "macro" in pretty much any other context. –  morbusg Apr 1 '11 at 16:44
add comment

Joseph already explained why and how it works. Here an alternative way to do this without using \expandafter to much:

Instead of using the @top macro as part of an argument, you can define it to "call" the parse macro with the top of the stack:

\def\MB@modulestack@top{\expandafter\MB@modulestack@top@call\MB@modulestack\relax}
\def\MB@modulestack@top@call#1#2\relax#3{#3#1}% here #1 are the four {.}{.}{.}{.} pushed on the stack

The parse macro simple receives the four arguments:

\def\MB@modulestack@topitemparse#1#2#3#4{%
  % do what you want with the four arguments
}

Usage:

\MB@modulestack@top\MB@modulestack@topitempars

The \MB@modulestack@topitempars could also be hardcoded into \MB@modulestack@top@call.

share|improve this answer
add comment

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.