8

In various contexts I define a macro such as

\makeatletter
\newcommand\aedosomething{\ae@do@something}
\def\ae@do@something#1#2#3{%%
   %% do something with arguments #2 and #3
   \def#1{<result of doing something>}}
\makeatother

Here's a bit fuller (though pointless example)

\makeatletter
\newcommand\aesavesumas{\ae@save@sum@as}
\def\ae@save@sum@as#1#2#3{%%
    \pgfmathparse{#2+#3}%%
    \edef#1{\pgfmathresult}}
\makeatother

In this particular instance, I am aware that there's a perfectly good macro

\pgfmathsetmacro

which is capable of computing and storing the information. But my question isn't about the particulars of what's done with the extra arguments. What I want to know is if I write something like

\global\aesavesumas\mysum{2}{3}

how to get the macro \aesavesumas to know that it should make the definition global so that, if \aesavesumas\mysum{2}{3} is called within a particular scope, the definition is saved for later use outside of that scope.

  • You can't; \global performs expansion until it finds something legal after it (\def, \chardef, \advance and so on; an assignment, to be precise), raising an error otherwise. Then the assignment is performed globally and \global disappears without leaving any trace: the information that the assignment was global cannot be accessed to. – egreg Oct 22 '14 at 7:03
6

The prefix \global can only go in front of an assignment. However, TeX expands tokens after \global in order to find the assignment. An example is the \booltrue macro in etoolbox:

\newrobustcmd*{\booltrue}[1]{%
  \ifcsundef{if#1}
    {\etb@noglobal\etb@err@nobool{#1}}
    {\csname#1true\endcsname}}

If one does \global\booltrue{foo}, the latter macro is expanded leaving

\global\ifcsundef{iffoo}{...}{...}

and \ifcsundef is expanded; in case \iffoo is defined, TeX finds

\global\footrue

that needs another step of expansion for arriving to the final step

\global\let\iffoo\iftrue

that's the assignment TeX was looking for. In case \iffoo is not defined, TeX will have \global\etb@noglobal that becomes \global\let\relax\relax and it's an assignment that does nothing (except perhaps polluting the save stack, but it's unimportant, because an error message will be issued).

The problem is that the information whether the last assignment was global cannot be accessed to, nor can the information that the expansion was triggered by a lonesome \global hunting for a mate assignment.

Your assignment \edef#1 comes in too late. Moreover \pgfmathparse begins with \begingroup and so you're doomed.

There's no problem instead if you use a postfix rather than a prefix. You can easily set up things so that \global is added when the call is

\aesavesumas*\mysum{2}{3}

and not when the * is missing.

| improve this answer | |
  • This is more of an aesthetic question: Would it be better to create a starred version of the command or to call \aesavesumas\mysum{2}{3} and then immediately \xdef\mysum{\mysum} or some other explicit global assignment? – A.Ellett Oct 22 '14 at 16:06
  • 1
    @A.Ellett I'd avoid \xdef\mysum{\mysum} because of local-global assignment that's evil. However, the same effect is obtained with \global\let\mysum\mysum (since \mysum has already been defined with \edef). – egreg Oct 22 '14 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.