8

This must be another of those expansion related issues as I don't know why the following

\def\MaxValueOfTok{8}%
\newtoks{\SomeTokDefinedViaDef}
\SomeTokDefinedViaDef={\MaxValueOfTok}

\pgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedViaDef}%

fails with

Package PGF Math Error: Unknown operator 8' or 8@' (in '10-8').

If possible, would prefer a solution that requires only changing the \pgfmathsetmacro computation, and not require any changes to how the token is defined. Alternatively, adjusting how the \def is set up would work as well.

Un-commenting the last two lines in the MWE will reproduce the problem.

Code:

\documentclass{article}
\usepackage{tikz}% Easy way to get pgfmath

\def\MaxValueOfTok{8}%

\newtoks{\SomeTokDefinedDirectly} \newtoks{\SomeTokDefinedViaDef}

\SomeTokDefinedDirectly={7} \SomeTokDefinedViaDef={\MaxValueOfTok}

\begin{document} \pgfmathsetmacro{\Difference}{10-5}% Differerence is \Difference (numerical).

\pgfmathsetmacro{\Difference}{10-\MaxValueOfTok}% Differerence is \Difference (using def).

\pgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedDirectly}% Differerence is \Difference (using SomeTokDefinedDirectly).

%\pgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedViaDef}% %Differerence is \Difference (using SomeTokDefinedViaDef). \end{document}

Peter Grill
  • 223,288

3 Answers3

9

You can do complete expansion beforehand:

\documentclass{article}
\usepackage{pgf}% Easy way to get pgfmath

\def\epgfmathsetmacro#1#2{\begingroup
  \edef\x{\endgroup\noexpand\pgfmathsetmacro\noexpand#1{#2}}\x}

\def\MaxValueOfTok{8}%

\newtoks\SomeTokDefinedDirectly
\newtoks\SomeTokDefinedViaDef

\SomeTokDefinedDirectly={7}
\SomeTokDefinedViaDef={\MaxValueOfTok}

\begin{document}
\epgfmathsetmacro{\Difference}{10-5}%
Differerence is \Difference (numerical).

\epgfmathsetmacro{\Difference}{10-\MaxValueOfTok}%
Differerence is \Difference (using def).

\epgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedDirectly}%
Differerence is \Difference (using SomeTokDefinedDirectly).

\epgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedViaDef}%
Differerence is \Difference (using SomeTokDefinedViaDef).
\end{document}
egreg
  • 1,121,712
7

You'll have to expand it manually, using 10\expandafter-\the\SomeTokDefinedViaDef.

\documentclass{article}
\usepackage{tikz}% Easy way to get pgfmath

\def\MaxValueOfTok{8}%

\newtoks{\SomeTokDefinedDirectly}
\newtoks{\SomeTokDefinedViaDef}

\SomeTokDefinedDirectly={7}
\SomeTokDefinedViaDef={\MaxValueOfTok}

\begin{document}
\pgfmathsetmacro{\Difference}{10-5}%
Differerence is \Difference (numerical).

\pgfmathsetmacro{\Difference}{10-\MaxValueOfTok}%
Differerence is \Difference (using def).

\pgfmathsetmacro{\Difference}{10-\the\SomeTokDefinedDirectly}%
Differerence is \Difference (using SomeTokDefinedDirectly).

\pgfmathsetmacro{\Difference}{10\expandafter-\the\SomeTokDefinedViaDef}%
Differerence is \Difference (using SomeTokDefinedViaDef).
\end{document}
Jake
  • 232,450
6

Another option is to replace pgfmath by l3fp from the l3kernel bundle. The parser in l3fp takes care of expanding everything; it also unpacks the contents of \toks and other registers. No need for \the.

\documentclass{article}

%% Load expl3 for l3fp, and xparse for \NewDocumentCommand.
\usepackage{expl3, xparse}
\ExplSyntaxOn
\NewDocumentCommand {\explfpsetmacro} { m m }
  { \tl_set:Nx #1 { \fp_to_tl:n {#2} } }
\ExplSyntaxOff
%%

\def\MaxValueOfTok{8}%

\newtoks{\SomeTokDefinedDirectly}
\newtoks{\SomeTokDefinedViaDef}

\SomeTokDefinedDirectly={7}
\SomeTokDefinedViaDef={\MaxValueOfTok}

\begin{document}
\explfpsetmacro{\Difference}{10-5}%
Differerence is \Difference (numerical).

\explfpsetmacro{\Difference}{10-\MaxValueOfTok}%
Differerence is \Difference (using def).

\explfpsetmacro{\Difference}{10-\SomeTokDefinedDirectly}%
Differerence is \Difference (using SomeTokDefinedDirectly).

\explfpsetmacro{\Difference}{10-\SomeTokDefinedViaDef}%
Differerence is \Difference (using SomeTokDefinedViaDef).
\end{document}

A few things to note:

  • at the moment, pgfmath provides more functions than l3fp;
  • computations with l3fp are much more precise (16 digits floating points, versus the range of TeX's dimensions);
  • speed is comparable;

  • a few functions will most likely never be implemented for use within l3fp expressions, namely box measurements (\widthof...) and random numbers.