Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

(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
\advance\pgfkeys@tempcnta\@ne
\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.

share|improve this question
    
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
3  
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

2 Answers 2

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 ...}.

share|improve this answer
1  
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
  ...
}
share|improve this answer
    
No comment, just a vote (upwards). –  Loop Space Apr 21 '12 at 20:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.