2

Is it possible to create an optional argument for a \pgfmathdeclarefunction?
Something like \pgfmathdeclarefunction{Plus}{2}[1.567]{\pgfmathparse{#1+#2}}, where #1 becomes 1.567 at Plus(2), but #1 becomes 1 at Plus(1,2).

\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{tikz}

\pgfmathdeclarefunction{Plus}{2}{\pgfmathparse{#1+#2}}
% Should be 
% \pgfmathdeclarefunction{Plus}{2}[1.567]{\pgfmathparse{#1+#2}}

\begin{document}
Test: \pgfmathparse{Plus(1,2)}\pgfmathresult

% \pgfmathparse{Plus(2)} should be 3.567
\end{document}

1 Answer 1

6

Yes, this is possible. \pgfmathdeclarefunction can use the argument count ..., which means an arbitrary number of comma separated arguments. pgfmath will then parse these arguments into a list of braced things, e.g., 1,2,3 will be turned into {1}{2}{3}. Inside the function definition we can now handle this list (which we'll get as a single argument).

The following uses \tl_count:n (assigned to another name) to count the number of arguments, and branching accordingly.

EDIT: PGF is inconsistent in how it forwards the arguments of a function being defined with .... If you just pass in a single argument it doesn't wrap it in braces. But if you pass in a single argument in braces the braces stay. Thanks to ghlecl for reporting this! So overall the syntax requires a bit of extra parsing. For this reason the following was edited to not only borrow \tl_count:n but also \tl_if_head_is_group:nTF.

\documentclass[]{article}

\usepackage{pgfmath}

\ExplSyntaxOn
\cs_new_eq:NN \tlcount \tl_count:n
\cs_new_eq:NN \tlifheadgroup \tl_if_head_is_group:nTF
\ExplSyntaxOff
\pgfmathdeclarefunction{cisplus}{...}
  {%
    \begingroup
      \tlifheadgroup{#1}
        {%
          \edef\tmp{\tlcount{#1}}%
          \ifnum\tmp>2
            \GenericError{}{! cisplus Error: Too many arguments}{}{}%
          \fi
          \ifnum\tmp=1
            \cisplusNEXT#1{1.567}% <- the default
          \else
            % #1 will contain {arg1}{arg2} (or more, in which case we already
            % threw the error and the behaviour of the following is undefined
            \cisplusNEXT#1%
          \fi
        }%
        {\cisplusNEXT{#1}{1.567}}% <- the default
      \pgfmathsmuggle\pgfmathresult
    \endgroup
  }
\newcommand\cisplusNEXT[2]{\pgfmathparse{#1+#2}}

\begin{document}
\pgfmathparse{cisplus(145)}\pgfmathresult

\pgfmathparse{cisplus({145})}\pgfmathresult

\pgfmathparse{cisplus(2,3)}\pgfmathresult

% throws an error:
% \pgfmathparse{cisplus(2,3,4)}\pgfmathresult
\end{document}

enter image description here

3
  • 1
    This answer unfortunately fails for me with one argument as soon as there is more the 2 digits, i.e. anything higher than 9. For instance,\pgfmathparse{cisplus(87)}\pgfmathresult just adds 8 and 7 to give 15. This is because the first "argument parsing" in the function does not yield an array when a single parameter is used, but just the number. The digits will then be counted as tokens and the function thinks there are two arguments when there is only one. Haven't figured out a way to make it work, but thought I would relate the bug with the code.
    – ghlecl
    Sep 23, 2021 at 15:09
  • 1
    @ghlecl you're right, PGF forwards a single argument without braces (which I find very unintuitive). Parsing is much harder this way... But the code is now fixed, thanks for reporting!
    – Skillmon
    Sep 23, 2021 at 15:34
  • Thank you so much. I am relatively new at this programming LaTeX thing (although I program in other langages a lot), and even though I got the idea to check if the next char is "begin group" (or something like that), I could not make it work. You have solved it in a few seconds/minutes. Again, thank you.
    – ghlecl
    Sep 23, 2021 at 16:00

You must log in to answer this question.

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