3

I am trying to have a "base" common implementation of two pgfmath functions defined via \pgfmathdeclarefunction which vary only by one number. I have successfully done so and when I print the results within the inner function/common implementation, everything works fine. My problem is I can't seem to get the value out via \pgfmathresult.

I have tried \pgfmathparse, \pgfmathsetmacro and setting \pgfmathresult directly via \edef. Nothing seems to work. I know \pgfmathresult is reused for a lot of computations inside pgf, but I thought my usage was "safe" in the sense that I "smuggle" the value out and I use it right after.

Is it that what I am trying to do is not supported at all ?

Here is a minimal working example which has the same behavior (my actual function as much more code) my problem.

\documentclass{minimal}
\usepackage{pgf}
\usepackage{pgfmath}

\ExplSyntaxOn

\pgfmathdeclarefunction{fn_impl}{...}{%
\begingroup%
   \pgfmathparse{12.0}\pgfmathsmuggle\pgfmathresult%
\endgroup%
}

\pgfmathdeclarefunction{fn}{...}{%
\begingroup%
   \pgfmathparse{fn_impl(#1)}\pgfmathsmuggle\pgfmathresult%
\endgroup%
}

\ExplSyntaxOff

\begin{document}
Simply parsing value:~\pgfmathparse{12.0}\pgfmathresult%

Calling fn(1.3,3.0,1.5):~\pgfmathparse{fn(1.3,3.0,1.5)}\pgfmathresult
\end{document}

The code outputs:

Simply parsing value: 12.0

Calling fn(1.3,3.0,1.5): 1.5

But I would expect:

Simply parsing value: 12.0

Calling fn(1.3,3.0,1.5): 12.0

What part of my understanding is wrong. Thanks for any help.

1
  • 1
    A better approach than forwarding the arguments as another pgfmath function's arguments would be to have a single internal macro that expects the arguments in the ... notation, so that you don't have to do those tricks with unbracing and adding commas.
    – Skillmon
    Sep 28, 2021 at 8:31

1 Answer 1

1

Your issue is the way PGF forwards the ... argument specification to the underlying macro. If you hand in only a single argument you'll get it as is, if you pass it multiple arguments you'll get a list in the form {arg1}{arg2}{arg3}..., but this doesn't work if you forward it directly to the next pgfmath function. Instead you'd have to unwrap the arguments and pass them in comma separated.

The following does that using expl3 (this might fail if one of the args need to be wrapped in braces):

\documentclass{minimal}
\usepackage{pgf}
\usepackage{pgfmath}

\pgfmathdeclarefunction{fn_impl}{...}{%
  \begingroup%
    \pgfmathparse{12.0}\pgfmathsmuggle\pgfmathresult%
  \endgroup%
}

\pgfmathdeclarefunction{fn}{...}{%
  \begingroup%
    \forwarddotargs{fn_impl}{#1}% <- calls pgfmathparse
    \pgfmathsmuggle\pgfmathresult%
  \endgroup%
}

\ExplSyntaxOn
\cs_new:Npn \forwarddotargs #1#2
  {%
    \tl_if_head_is_group:nTF {#2}
      {
        \__ghleci_forwarddotargs_auxi:en
          { \tl_map_tokens:nn {#2} { , \exp_not:n } }
          {#1}
      }
      { \pgfmathparse { #1 (#2) } }
  }
\cs_new:Npn \__ghleci_forwarddotargs_auxi:nn #1
  { \__ghleci_forwarddotargs_auxii:on { \use_none:n #1 } }
\cs_generate_variant:Nn \__ghleci_forwarddotargs_auxi:nn { e }
\cs_new:Npn \__ghleci_forwarddotargs_auxii:nn #1#2
  { \pgfmathparse { #2 (#1) } }
\cs_generate_variant:Nn \__ghleci_forwarddotargs_auxii:nn { o }
\ExplSyntaxOff

\begin{document}
Simply parsing value:~\pgfmathparse{12.0}\pgfmathresult%

Calling fn(1.3,3.0,1.5):~\pgfmathparse{fn(1.3,3.0,1.5)}\pgfmathresult
\end{document}
2
  • I have no choice but to accept that this might be my problem, since your solution works, but I fail to see how it relates to the problem. Especially since I was able to get the parameter values in my inner function in my tests. :-( Could you explain why the \use_none:n is required? I am reading the documentation (interface3.pdf), but can't understand it. I have also tried with a non pgf macro, but was unable to make it work. Thanks.
    – ghlecl
    Sep 28, 2021 at 11:59
  • 1
    @ghlecl the \use_none:n removes the first comma. I build the argument by looping over every item in the {arg_1}...{arg_n} list leaving , arg_i for every argument. Hence after the first step I'd get , arg_1, ..., arg_n (without the spaces). As to why PGF fails here: No idea, I find the design decisions of the ... arguments strange, tbh. And I have no idea why fn_impl({arg1}{arg2}{arg3}) doesn't result in the \pgfmathresult being what you smuggled.
    – Skillmon
    Sep 28, 2021 at 12:05

You must log in to answer this question.

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