(1) In the expression

\def\pgfkeysgetvalue#1#2{\expandafter\let\expandafter#2\csname pgfk@#1\endcsname}


#2 will be let to \relax whenever pgfk@#1 is undefined. Is this harmless in pgf? Even if it was benign, why isn't a more formal coding style adopted.

(2) In the expression

\def\pgfkeysvalueof#1{\csname pgfk@#1\endcsname}


\pgfkeysvalueof{#1} will be simply \relax if the name pgfk@#1 was undefined. The arguments of \csname pgfk@#1\endcsname will then be unabsorbed (and, eg, will result in \@nodocument outside LaTeX document environment). Why isn't it necessary to first check for the existence of the name pgfk@#1?

(3) Why wasn't the following expression made more compact by a simple abstraction?

\long\def\pgfkeysdefnargs@#1#2#3#4{%
\ifcase#2\relax
\pgfkeyssetvalue{#1/.@args}{}%
\or
\pgfkeyssetvalue{#1/.@args}{##1}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8}%
\or
\pgfkeyssetvalue{#1/.@args}{##1##2##3##4##5##6##7##8##9}%
\else
\pgfkeys@error{\string\pgfkeysdefnargs: expected  <= 9 arguments, got #2}%
\fi
...
}


Here is a pseudocode for the abstraction I mean:

initialize \pgfkeys@temptoks, \pgfkeys@tempcnta
\loop
\edef\x{%
\pgfkeys@temptoks{\the\pgfkeys@temptoks\ifnum\pgfkeys@tempcnta
<\numexpr#1+1\relax<parameter chars>\the\pgfkeys@tempcnta\fi}%
}\x
\ifnum\pgfkeys@tempcnta<#1\relax
\repeat


Here, you can avoid eTeX if you like.

-
I think for the second question the answer it is a little bit faster with an ifcase rather than a \loop..\repeat. –  Yiannis Lazarides Apr 17 '12 at 19:18
I'm curious as to why you want to know. The "real" answers are "the person who wrote it did it that way, and that person isn't on TeX-SX [to my knowledge] so anything else is pure speculation.". Maybe you're interested in optimising TeX code and are using these as examples, but that's not clear from your questions. You've asked quite a few technical questions about pgfkeys and I'm curious as to where it's heading. –  Loop Space Apr 17 '12 at 19:52
@YiannisLazarides: pgfkeys is already much slower than, say, xkeyval. It has a rather lengthy method. –  Ahmed Musa Apr 21 '12 at 19:48

There is no check in \pgfkeysgetvalue and \pgfkeysvalueof because these methods assume that the key in question exists.

In fact, \pgfkeysvalueof is designed to be expandable (for example using \edef\temp{\pgfkeysvalueof{/pgf/key}}). There simply is no way of sanity checking here (except for lua hacking perhaps).

The preferred way to check for keys is to use \pgfkeysifdefined{/pgf/key}{\pgfkeysgetvalue{/pgf/key}\temp}{... error handler ...}.

-
There is one other thing which might is not an answer, only a thought: while sanity checking in general is quite important, there is a difference between internal usage and external usage. Any public usage of keys should be done using \pgfkeys - which does sanity checking including sophisticated fallbacks. And internal usage... well, is internal. You probably would not query values for keys which you have never defined in your internal implementation - and if you did, you would hopefully realize it in your tests. –  Christian Feuersänger Apr 21 '12 at 22:01
Thanks for the reminder on \pgfkeysifdefined. But expandability of a function and checking for existence of the argument of the function are two different things, depending on the callbacks involved. If one of the callbacks is not expandable, then of course there might be a problem. For example, etoolbox's \csuse does check for existence of its argument and it is expandable. I've had cause to call \pgfkeysvalueof for keys I didn't define. –  Ahmed Musa Apr 22 '12 at 10:33
Well, sanity checks are necessary for sure. The question is when and where... and if you agree with me that \pgfkeysifdefined is a suitable check, than all is well. Just for the records: in case \pgfkeysvalueof would apply sanity checking (which is possible since the if statements are expandable too), it could not react to a failed check. At least not if it is used in expandable content: it can only expand to some magic "this is undefined" value which has to be checked at a higher level. –  Christian Feuersänger Apr 22 '12 at 14:37

At the risk of drawing a comment from Andrew Stacey, here is what I had in mind, which has been included in pgfkeys-patch.

\pgfkeysnewdef*\pgfkeys@generateparameters#1#2{%
\ifnum#1<\numexpr#2+1\relax ####\number#1%
\expandafter\pgfkeys@generateparameters
\expandafter{\number\numexpr#1+1\expandafter}%
\expandafter{\number#2\expandafter}%
\fi
}
% Thanks to eTeX, \pgfkeys@generateparameters is expandable.
\pgfkeysnewdef\pgfkeysdefnargs@#1#2#3#4{%
\ifnum#2>9\relax
\pgfkeys@error{\string\pgfkeysdefnargs: I expected #2<=9 arguments but I saw #2}%
\else
\pgfkeyscsedef{pgfk@#1/.@args}{\pgfkeys@generateparameters{1}{#2}}%
\fi
...
}

-
No comment, just a vote (upwards). –  Loop Space Apr 21 '12 at 20:11