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 finally developed from egreg's answer in my previous question ( Defining a macro with three optional arguments in the form \newmacro{a}{b}[c]{d}[e][f] and \newmacro{a}{b}[c]{d}*[f] ) While my original answer was about making a shorter code, I ended up with a ~190 lines package. For the curious you can check it here in github, and it is also documented here.

The macro works fine, except for a display mode I would like to achieve: I want the macro to work inside tabular environments such as array or align: that would allow to typeset several function definitions preserving some alignment.

However I found a problem.

Let's took a look of the following code:

\documentclass{article}
\def\tempi{0}
\def\tempii{1}
\newcommand\mymacro[1]{
  \let\tempiii\tempi
  \def\tempi{#1\tempiii}
  \def\tempii{#1}
  \mymacroi
}
\newcommand\mymacroi{\tempi & \tempii}
\begin{document}
\[
  \begin{array}{cccc}
    a & \mymacro{1} & b \\
    \mymacro{2} & \mymacro{3}
  \end{array}
\]
\end{document}

It gets this result: a 10 1 b // 20 1 30 1

Changing the definition of \mymacroi

\newcommand\mymacroi{\tempi , \tempii}

The new result is: 1 10,1 b // 20,2 30,3

In the first code, the changes in \tempii are not preserved after the tab character &. The second one shows the modification of \tempii (but does not align).

Using \begingroup in \mymacro:

\newcommand\mymacro[1]{
  \begingroup
  \let\tempiii\tempi
  \def\tempi{#1\tempiii}
  \def\tempii{#1}
  \mymacroi
  \endgroup
}

And, with the original \mymacroi (the one with &) I get an error.

So the problem is indeed trying to use & from the macro, while preserving changes local to my macro, while expanding these changes over several cells.


(In this MWE there is a circular reference which does not exist in my original macro.)


Update:
My original example was too simple to show some desired result, and given that my macro should work both inside tabular environment and non-tabular environments, I will mimic that in this MWE by redefining \mymacroi. I copy only the document environment.

\begin{document}
\[
  \begin{array}{cccccc}
    a & \mymacro{7} & b & \tempi & \tempii \\
    \mymacro{2} & \mymacro{3} & \tempi & \tempii 
  \end{array}
\]
\renewcommand\mymacroi{%
  \edef\tmp{\tempi,\tempii}%
  \tmp
}
\par Test 1 \(\mymacro{5};\tempi,\tempii\)
\par Test 2 \(\mymacro{4};\tempi,\tempii\)
\end{document}

The expected result is:
array-check
and
non-array-check

share|improve this question

2 Answers 2

Each of the cells within the table forms a group. So, your use of

\mymacro{2}

expands to

\let\tempiii\tempi
\def\tempi{2\tempiii}
\def\tempii{2}
\mymacroi

which defines \tempi as 2\tempiii (which is equivalent to 2\tempi) and \tempii as 2. Then you call \mymacroi which expands to

\tempi & \tempii

Both \tempi and \tempii are defined, but the updated definition was done inside the (first) group/cell. As such, the second cell containing \tempii would revert back to the original definition (as done in the preamble as \def\tempii{1}). This happens with every use of \mymacro, and it seems like you wish to have your local re-definitions to span across these cells. To do that, use a global re-definition (or possibly an expanded global re-definition):

enter image description here

\documentclass{article}
\newcommand\tempi{0}
\newcommand\tempii{1}
\makeatletter
\newcommand{\storetemps}{%
  \global\let\store@tempi\tempi%
  \global\let\store@tempii\tempii}
\newcommand{\restoretemps}{%
  \global\let\tempi\store@tempi%
  \global\let\tempii\store@tempii}
\newcommand\mymacro[1]{
  \storetemps%
  \xdef\tempi{#1\tempi}%
  \xdef\tempii{#1}%
  \mymacroi%
}
\newcommand\mymacroi{%
  \ifnum\pdfstrcmp{\@currenvir}{array}=0
    \let\select@type\@firstoftwo%
  \else
    \let\select@type\@secondoftwo%
  \fi
  \select@type{\tempi & \tempii}{\tempi, \tempii}%
  \restoretemps%
}
\makeatother

\begin{document}
$
  \begin{array}{cccccc}
    a & \mymacro{7} & b & \tempi & \tempii \\
    \mymacro{2} & \mymacro{3} & \tempi & \tempii 
  \end{array}
$

Test 1 \(\mymacro{5};\tempi,\tempii\) \par
Test 2 \(\mymacro{4};\tempi,\tempii\)
\end{document}

The above version of \mymacroi conditions on whether you're in an array environment or not, allowing you to use it as-is inside one or not.

share|improve this answer
    
This solves part of the problem: having \tempii preserved inside \mymacro over the cells. But then \tempii is also redefine outside \mymacro which is not desired. This example was probably too simple to show that part of the intended effect. –  Carlos Eugenio Thompson Pinzón Dec 15 '13 at 3:58
    
@CarlosEugenioThompsonPinzón: Yes, it doesn't make sense, since \tempii is used nowhere else. However, you could use an alternative macro name, or restore it using another \gdef after using it. But I would need more information to clearly help you. –  Werner Dec 15 '13 at 5:13
    
I updated the question to add a more complicated example showing desired effect. See also comment to David's answer. –  Carlos Eugenio Thompson Pinzón Dec 15 '13 at 12:57
1  
@CarlosEugenioThompsonPinzón: I've updated my answer. Let me know if it works for you now. –  Werner Dec 15 '13 at 15:38

enter image description here

You appear to want to expand the macros in the current group but evaluate them in a different group, so separate expansion and typesetting with \edef (or if there are any user supplied LaTeX input, \protected@edef). Also you had several % missing from ends of lines.

\documentclass{article}
\def\tempi{0}
\def\tempii{1}
\newcommand\mymacro[1]{%
  \let\tempiii\tempi
  \def\tempi{#1\tempiii}%
  \def\tempii{#1}%
  \mymacroi
}
\newcommand\mymacroi{%
\edef\tmp{\tempi&\tempii}%
\tmp}

\begin{document}
\[
  \begin{array}{cccc}
    a & \mymacro{1} & b \\
    \mymacro{2} & \mymacro{3}
  \end{array}
\]
\end{document}
share|improve this answer
    
My current actual macro is working with \begingroup, \endgroup, as there are too many variables that might be touched and need to be reseted for the next call. I've upvoted your answer and updated (and complicated) the request. –  Carlos Eugenio Thompson Pinzón Dec 15 '13 at 12:54
1  
@CarlosEugenioThompsonPinzón I don't see the updated question changes anything, this produces the desired result. You can't use grouping as you want the results to be visible in a different group. & & is a group the same as { } as far as macro expansion is concerned. So I wouldn't change this answer given the updated question. –  David Carlisle Dec 15 '13 at 14:23

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.