2

It seems that pgfkeys is attempting to do math on one of my arguments, and failing because it's not actually math. How do I prevent this, and ensure that the argument is passed correctly?

Compiling using lualatex. The log records a single Missing number, treated as zero. and then

Package PGF Math Error: You've asked me to divide `1' by `', but I cannot divide any number by `' (in '(0) + (1/, 1/A, 1/-1 B, 1/-2 C,)').

I have tried several variations on putting {} around things, and in place of empty text, and so forth. It might be related to the sum=auto, but just typing the text in does work, so something is still changing in pgfkeys.

MWE below:

\documentclass[twoside,headings,a4paper]{article}
\usepackage{xparse}
\usepackage{pgfkeys}
\usepackage{pgf-pie}

\begin{document}

\pgfkeys{
    /TestExample/.is family, TestExample,
    % Here are the options that a user can pass
    default/.style = {
            TestPie = {},
        },
    TestPie/.store in = \TestPie,
}
\newcommand{\TestExample}[2][]{
    \clearpage
    \pgfkeys{TestExample, default, #1}%

    \begin{tikzpicture}
        \pie[color=white, hide number, text=inside, sum=auto, rotate=90, change direction]{
            1/,
            1/A,
            1/-1 B,
            1/-2 C
        }
    \end{tikzpicture}

    \begin{tikzpicture}
        \pie[color=white, hide number, text=inside, sum=auto, rotate=90, change direction]{
            \TestPie
        }
    \end{tikzpicture}

    #2
}

\TestExample[TestPie={
            1/,
            1/A,
            1/-1 B,
            1/-2 C
        }]{
    Blah Blah Blah
}
\end{document}
9
  • pgf-pie doesn't like the comma after the C, and it doesn't like it if you hide the numbers inside \TestPie. Commented Feb 6, 2023 at 9:30
  • @UlrikeFischer, Are you sure? It quite happily handles the comma after the C in the first example, where it is typed directly into the pie command. And of course, the question is how to make \TestPie work, or to work around whatever limitation is breaking it.
    – Tetragramm
    Commented Feb 6, 2023 at 14:43
  • yes I'm sure. And how do you know that it handles the comma? your example mixes everything together you can't actually know which part error when. Commented Feb 6, 2023 at 14:48
  • @UlrikeFischer, Well, I was going to say "because it works", but you are correct, that does actually cause errors. Still though, the problem stands, even with the last comma removed. I will edit the example to reflect that.
    – Tetragramm
    Commented Feb 6, 2023 at 15:05
  • 1
    @Tetragramm I have expanded the comment to a full answer. Commented Feb 8, 2023 at 19:25

3 Answers 3

3

Your \TestPie will be put in the place of a list, as in

\foreach \foo/\bar in {\TestPie} {<body>}

and since the first (and only) element of the list, \TestPie, doesn't contain a / it will let both \foo and \bar to \TestPie.

The first one will be thrown in PGFMath at some point which tries to evaluate the expansion of \TestPie – PGFMath always fully expands the formula – which does contain a / and PGFMath tries to divide … things.

You need to expand \TestPie at least once.

The least complex way to do this would be

\def\temp{\pie[color=white, hide number, text=inside,
               sum=auto, rotate=90, change direction]}
\expandafter\temp\expandafter{\TestPie}

The other answer shows a few e-TeX powered approaches.


However, you can also delegate the expansion to the internal \foreach loop by enabling

/pgf/foreach/expand list

which will lead PGFFor to fully expand all lists before iterating over them – or at least those that are used by \pie when it is given to the optional argment of \pie:

\pie[color=white, hide number, text=inside,
    sum=auto, rotate=90, change direction, /pgf/foreach/expand list]
{\TestPie}

This is not safe for fragile commands like \textbf inside the labels of the pie pieces.

But allow me to extend expand list so it does accepts – besides true and false – also once and then you can do

\pie[color=white, hide number, text=inside,
     sum=auto, rotate=90, change direction, /pgf/foreach/expand list=once]
{\TestPie}

pretty safely.

(Yes, this will expand the first token of every PGFFor loop that's used in \pie.)

Code

\documentclass[twoside,headings,a4paper]{article}
\usepackage{xparse}
\usepackage{pgfkeys}
\usepackage{pgf-pie}
\makeatletter
\pgfqkeys{/pgf/foreach/expand list}{
  .code=\csname pgffor@expand@list@#1\endcsname,
  .default=true}
\def\pgffor@expand@list@once{%
  \def\pgffor@expand@list##1{%
    \expandafter\def\expandafter##1\expandafter}}
\makeatother
\begin{document}
\pgfkeys{
  /TestExample/.is family, TestExample,
  % Here are the options that a user can pass
  default/.style = {
          TestPie = {},
      },
  TestPie/.store in = \TestPie,
}
\newcommand{\TestExample}[2][]{%
  \clearpage
  \pgfkeys{TestExample, default, #1}%
  \begin{tikzpicture}
      \pie[color=white, hide number, text=inside,
           sum=auto, rotate=90, change direction]{
          1/,
          1/A,
          1/-1 B,
          1/-2 C
      }
  \end{tikzpicture}
  \begin{tikzpicture}
      \def\temp{\pie[color=white, hide number, text=inside,
                     sum=auto, rotate=90, change direction]}
      \expandafter\temp\expandafter{\TestPie}
  \end{tikzpicture}
  \begin{tikzpicture}
      \pie[color=white, hide number, text=inside,
          sum=auto, rotate=90, change direction, /pgf/foreach/expand list=once]
      {\TestPie}
  \end{tikzpicture}
  #2}

\TestExample[
  TestPie={
    1/,
    1/A,
    1/-1 B,
    1/-2 \textbf{C}
  }]{Blah Blah Blah}
\end{document}
1
  • Just for clarification (minor nitpicking): \expanded is not e-TeX but a primitive of the major engines. Else really good analysis of what's going wrong why, +1.
    – Skillmon
    Commented Feb 9, 2023 at 7:29
3

You need to expand the value of \TestPie before pgf-pie tries to parse its argument. As an idiom you can use

\expanded{\unexpanded{<stuff>}\expandafter}

to use one step of expansion before <stuff> is considered. That can be used to expand your macro once.

If this is needed multiple times or you want it to be more semantically clear you can define a macro:

\newcommand\expandafterthings[1]{\expanded{\unexpanded{#1}\expandafter}}

So your call to \pie could look like the following:

\expandafterthings
  {\pie[color=white, hide number, text=inside, sum=auto, rotate=90, change direction]}\expandafter{\TestPie}

If you know that \TestPie and all your options are safe against a full expansion you could also use

\expanded{\noexpand\pie[<options>]{\TestPie}}
1

The answer below uses the wheelchart package, which I wrote.

The described issue does not occur in the answer below.

enter image description here

\documentclass[border=6pt]{standalone}
\usepackage{wheelchart}
\begin{document}
\pgfkeys{
  /TestExample/.is family,
  TestExample,
  % Here are the options that a user can pass
  default/.style={TestPie={},},
  TestPie/.store in=\TestPie,
}
\newcommand{\TestExample}[2][]{%
%\clearpage
\pgfkeys{TestExample,default,#1}%
\pgfkeys{
  /wheelchart,
  data=,
  pie,
  slices style={
    fill=none,
    draw
  },
  wheel data=\WCvarB
}%
\begin{tikzpicture}
\wheelchart{1/,1/A,1/-1 B,1/-2 C}
\end{tikzpicture}
\begin{tikzpicture}
\wheelchart{\TestPie}
\end{tikzpicture}
#2}
\TestExample[TestPie={1/,1/A,1/-1 B,1/-2 \textbf{C}}]{Blah Blah Blah}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .