5

When using pfgmathsetmacro in commands (defined by \newcommand) we have a problem of locality of variables. For instance if you design two functions

\newcommand\f[4]{%
  \pgfmathsetmacro#3{cosh(#1+#2)}%
  \pgfmathsetmacro#4{cos(#1+#2)}%
}
\newcommand\g[4]{%
  \pgfmathsetmacro#3{sqrt(1+(#1-#2)^2)}%
  \pgfmathsetmacro#4{sqrt((#1)^2+(#2)^2)}%
}

and want to define the composed function

\newcommand\h[4]{%
  \f#1#2\x\y%
  \g\x\y#3#4%
}

How do you protect the variables \x and \y such that you do not have to worry about not naming other variables \x or \y ? If you have only one variable, the problem can be avoided using \pgfmathresult, but what if you have two (or more !) variables ?

6
  • 1
    Using \begingroup \endgroup pushes the contents of all registers onto the stack, then restores them when done. In other words, what happens in a scope stays in a scope (unless you use \global}. Jul 3, 2014 at 13:46
  • OTOH, why are you using \pgfsetmacro instead of just executing the commands with the given arguments? You still need to save \pgfmathresult after each. Jul 3, 2014 at 13:48
  • Please ignore my last comment. Jul 3, 2014 at 13:51
  • @JohnKormylo. Thank you for this idea about \begingroup/endgroup !
    – Tom-Tom
    Jul 3, 2014 at 14:03
  • @JohnKormylo. There is still something that escapes about your answer: if you define \newcommand\h[4]{\begingroup\f#1#2\x\y \g\x\y#3#4 \endgroup} how is the content of \h{1}{2}\x\y retrieved ? Why isn't it lost after \endgroup ?
    – Tom-Tom
    Jul 3, 2014 at 15:02

2 Answers 2

6

I'll show a simplified version with one variable functions:

\documentclass{article}
\usepackage{tikz}

\newcommand\funcF[2]{%
  \pgfmathsetmacro#1{cosh(#2)}%
}
\newcommand\funcG[2]{%
  \pgfmathsetmacro#1{sqrt(#2)}%
}

\newcommand{\compose}[4]{%
  \begingroup
  #3\x{#4}%
  #2\x{\x}%
  \edef\x{\endgroup\noexpand\pgfmathsetmacro\noexpand#1{\x}}\x
}

\newcommand{\funcH}[2]{%
  \compose#1\funcG\funcF{#2}%
}

\begin{document}

\funcH\firstvalue{1}$\firstvalue$

\funcH\secondvalue{2}$\secondvalue$

\end{document}

The “local variable” \x is forgotten as soon as the final \x is executed.

enter image description here

Instead of \x you might want to use \AcOmMaNdNaMeThAtSpRoBaBlYnOtUsEd or something unusual like this.

Here's the response from bc -l, that shows that the functions are computed correctly, given the low precision with PGF:

> bc -l
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
sqrt((e(1)+e(-1))/2)
1.24220796761864467541
sqrt((e(2)+e(-2))/2)
1.93963803094382315206
0
1

Consider the following MWE:

\documentclass{article}
\setlength{\parindent}{0pt}

\newcommand{\h}[2]{%
\begingroup%
\edef\x{#1}
\global\edef#2{#1}
\endgroup}

\begin{document}

\def\x{0}
\def\y{1}

\h{2}{\y}

x=\x\newline
y=\y\newline

\end{document}

If you remove the \begingroup \endgroup, you will get x=2, y=2. If you remove the \global you will get x=0, y=1. (I don't know if \pgfmathsetmacro uses \global or not, but I would guess not.)

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.