# Does the order of specified key-values matter?

The following screen shot shows how the order of specified key-values affects the output.

1. When using dx=\psPiH,xunit=\psPi.

2. When using xunit=\psPi,dx=\psPiH.

Minimal Working Example

\documentclass[pstricks]{standalone}
\usepackage{pst-plot}

\psset{trigLabels=true,trigLabelBase=2,}

\begin{document}

\begin{pspicture}(-7,-2)(7,2)
\psaxes[dx=\psPiH,xunit=\psPi](0,0)(-2.2,-1)(2.2,1)
\end{pspicture}

\begin{pspicture}(-7,-2)(7,2)
\psaxes[xunit=\psPi,dx=\psPiH](0,0)(-2.2,-1)(2.2,1)
\end{pspicture}

\end{document}


It might be a bug. But does the order of specified key-values matter?

-
I think you answered the question, in general the order does matter. Certainly in the keyval system used by the graphicx package (and pstricks is very similar) they explicitly are evaluated in order (so that keys specifying scaling and rotation and origin offsets have a defined meaning if used together) – David Carlisle Jul 25 '12 at 13:51
While the example here is PStricks-based, the question itself seems entirely general. Would removing the pstricks tag be appropriate? – Joseph Wright Aug 3 '12 at 11:09

In general, the order of keys does matter where there is some interaction between the keys. That is because keys are normally processed in a left-to-right sense, and so the settings from the 'earlier' keys can be altered by those 'later' in the list.

There are cases where internally implementations use multiple pass approaches to setting keys. This is done for example by fontspec, which first checks basic detail of font in use before setting keys which make sense for that type.

It is possible to set up key-value methods such that order does not matter, for example by parsing them into an array which is then used in a fixed order. However, that is not something which most packages do, and would I hope be documented by any package using this method.

-

The order is only important if the keys depend to each other. dx is a PSTricks length and it can be used with or without a unit. Without a unit it takes the current value of psxunit into account! And that value is set by the key xunit. That is the expected behaviour of a relative length setting!

Using dx with an absolute length (has a unit like \psPiH cm) makes both keys independent:

\begin{pspicture}(-7,-2)(7,2)
\psaxes[dx=\psPiH cm,xunit=\psPi](0,0)(-2.2,-1)(2.2,1)
\end{pspicture}

\begin{pspicture}(-7,-2)(7,2)
\psaxes[xunit=\psPi,dx=\psPiH cm](0,0)(-2.2,-1)(2.2,1)
\end{pspicture}


will give the same output!

-

Although any key-value system gives the appearance of "setting properties" of some kind (for example, the numerical parameters of a picture), in fact to some extent they are all "calling methods" instead. I really only know about pgfkeys, which is not what you're asking about, but in that system, keys are as powerful as TeX macros and, therefore, can have arbitrarily complicated behavior. As Herbert answers, even for your example one key sets a default that is used by another key, and this is something you can expect to matter even for keys that basically just set properties.

It would be possible, as a programming question unrelated to TeX, to make the keys independent of order, which would involve setting a flag for each key and storing its value before actually acting on it. At the end of the list, one checks all the flags and resolves all interactions via numerous conditional statements, and finally uses the requested values in whatever way is implied by the keys in the list as a whole. Since this involves manually verifying all possible combinations of keys, and in the end is basically just establishing a default order (as in Joseph's answer), it is easier just to let the given order be the default, which is what is actually done.

-

Rearranging the order of setting keys internally (from a user key-value list) will be expensive. Setting the list twice may make the order of the list less relevant, but the key author has to exercise some caution.

Let us assume the following keys.

\mp@a depends on \mp@b that comes later, so we have to make the evaluation of \mp@a conditional on knowing \mp@b:

\define@key{fam}{a}[1cm]{%
\ifdefined\mp@b\edef\mp@a{\the\dimexpr#1+\mp@b}\fi
}
\define@key{fam}{b}[.5cm]{\def\mp@b{#1}}


The updated value of \mp@a will not be known until key b has been set.

Setting the list twice will make the order of the list less relevant. This can be achieved via the following

\newcount\setkeyscount
\def\setkeystwice{\@testopt\s@tkeystwice{KV}}
\def\s@tkeystwice[#1]#2#3{%
\setkeyscount\z@
\loop
\setkeys[#1]{#2}{#3}%
\ifnum\setkeyscount<\tw@
\repeat
}

\setkeystwice{a=1cm,b=2cm}


Here is a more formal approach, which requires no special conditionals in defining the keys. The key author only needs to call \orderofkeys with the right order of how he wants the keys to be set internally. Note that (i) \orderofkeys (actually, \XKV@setheadkeys) does not filter out 'current keys' (i.e., keys appearing in the user-supplied key-value list) from its preset list; and (ii) \orderofkeys takes a key-value list but the user can omit values for keys with default values.

\documentclass{article}
\usepackage{xkeyval}
\makeatletter

% \setkeystwice[<pref>]{<fam>}[<na>]{<kvlist>}
\def\setkeystwice{\XKV@testopta{\XKV@testoptc\XKV@setkeystwice}}
\def\XKV@setkeystwice[#1]#2{%
\ifnum\XKV@depth=\z@\let\XKV@rm\@empty\fi
\XKV@checksanitizea{#2}\XKV@tempb
\let\XKV@naa\@empty
\XKV@for@o\XKV@tempb\XKV@tempa{%
\expandafter\XKV@g@tkeyname\XKV@tempa=\@nil\XKV@tempa
}%
\expandafter\XKV@s@tkeystwice\expandafter{\XKV@tempb}{#1}%
}
\def\XKV@s@tkeystwice#1#2{%
% Set the usual xkeyval's head keys:
\XKV@usepresetkeys{#2}{preseth}%
\XKV@s@tkeys{#1}{#2}%
\XKV@s@tkeys{#1}{#2}%
% Set the usual xkeyval's tail keys:
\XKV@usepresetkeys{#2}{presett}%
\let\CurrentOption\@empty
}
% Unlike xkeyval package's \XKV@usepresetkeys, \XKV@setheadkeys instantiates
% head/ordered keys whether or not they appear in the current (user-supplied) key-value
% list.
\XKV@presettrue
\XKV@for@eo\XKV@fams\XKV@tfam{%
\XKV@makehd\XKV@tfam
\XKV@toks\expandafter\expandafter\expandafter
\@expandtwoargs\XKV@s@tkeys{\the\XKV@toks}{#1}%
}%
}%
\XKV@presetfalse
}

% Example use:

% We could have used command-keys to define these keys, but never mind:
\define@key{box}{boxwidth}[1cm]{\def\boxwidth{#1}}
\define@key{box}{boxheight}[.5cm]{\def\boxheight{#1}}
\define@key{box}{framecolor}[black]{\def\framecolor{#1}}
\define@key{box}{framesize}[.4pt]{\def\framesize{#1}}
\define@key{box}{boxsep}[5mm]{\def\boxsep{#1}}
% Note: \shadowsize is a fraction of \boxwidth plus \boxheight. [The ratio is given by
% the key 'shadowratio'.] Hence 'boxwidth' and 'boxheight' must be set before
% 'shadowratio'. We want to allow the user to set the keys in any order.
\def\tempa##1.##2\@nil{##1}%
\edef\tempa{\expandafter\tempa\the\dimexpr#1pt*100\relax\@nil}%
}

% Since the values of 'boxwidth' and 'boxheight' are needed when setting 'shadowratio',
% we preset/order 'boxwidth' and 'boxheight' before 'shadowratio'. The user could then
% set the keys in any order he likes.

% Let us define a sample method that uses these keys and \setkeystwice:
\usepackage{xcolor}
\newcommand*\somebox[2][]{%
\setkeystwice{box}{#1}%
\begingroup
\fboxrule=\framesize\relax
\setbox0=\hbox{%
\vbox to \boxheight{\vfil\hbox to\boxwidth{\hfil{#2}\hfil}\vfil}%
}%
}%
\rule[-\dp0]{\wd0}{\the\dimexpr\ht0+\dp0\relax}%