21

When I need to retrieve the value of a key in a macro, I use the key handlers .get and .store in. Here is what is written in the pgfkeys documentation:

Key handler key /.get= macro Executes a \let command so that macro contains the contents stored in key .

Key handler key /.store in= macro This handler has the following effect: When you write key = value , the code \def macro { value } is executed. Thus, the given value is “stored” in the macro .

I don't really understand the differences between these two handlers. Actually, I would expect .store in to be sufficient, and yet I need both. Why?

Code

Below is typically what I write (without understanding it...) when I use pgfkeys:

\documentclass[margin=.5cm]{standalone}
\usepackage{pgfkeys}

\newcommand{\DisplayKey}[1]{
\pgfkeys{
  /a/.initial=1,
  /a/.get=\aKey,
  /a/.store in=\aKey,
}
\pgfkeys{#1}
a is \aKey
}

\begin{document}
\DisplayKey{a=7}
\end{document}

Output

enter image description here

2
  • I use it generally to draw a figure with tikz. This is just a useless minimal example to illustrate my understanding of pgfkeys use. Maybe it will help someone get started. .initial is useless here but my point is that I need to use .get and .store in together if I want to be able to store the value.
    – remjg
    Aug 22, 2013 at 15:06
  • More confusion about .get and .initial: Complex objects in TikZ: pgfkeys scope and best practice Aug 23, 2013 at 9:21

5 Answers 5

17

Three answers in and much more confusion (at least on my side).


The handlers .get and .store in are very different and nothing alike.

The <key>/.store in=\<macro> handler sets up a key <key> so that if it is used with <key>=<value> it stores <value> in \<macro>. This is the same as if you would have written <key>/.code=\def\<macro>{#1}.

Every time you use the <key> the macro \<macro> will be (re) defined.

The .get handler actually kind of performs the opposite, it takes the current value of the key and stores it in a macro. An un-.initialized key will give you \relax.

The .get handler is only one of many ways to receive the value of a key in an easily usable macro. (Remember that the key itself is only a macro as well.) Other ways include \pgfkeysgetvalue{/full/path to/key}\<macro> or if you don’t need macro \pgfkeysvalueof{/full/path to/key}.


What you do with

\pgfkeys{
  /a/.initial=1,
  /a/.get=\aKey,
  /a/.store in=\aKey,
}

is bad practice because you first set up the key to be a “value key” and initialize it with the value 1. Then you get that 1 and save it in \aKey (that’s actually a \let but that is not important). Then you change the setup of the key to be a .store in key, a key that saves its value in a macro. That has nothing to do with the previous .initial key.

This is equivalent to

\def\aValue{1}
\let\aKey\aValue
\def\aCommand#1{\def\aKey{#1}}

One can see that \aValue serves no real purpose. And you actually have used three macros:

  • \aValue (\pgfk@/a),
  • \aKey and
  • \aCommand (\pgfk@/a/.@cmd).

The same can be achieved with

\def\aCommand#1{\def\aKey{#1}}
\aCommand{1}

or

\def\aCommand#1{\def\aKey{#1}}
\def\aKey{1}

or in PGFkeys:

\pgfkeys{
  /a/.store in=\aKey,
  /a=1 % this initializes \aKey
}

As discussed before in When to use a regular .initial key or a .store in key?, I consider .store in obsolete as you need two macros for every key:

  • one for the key itself that performs the \def and
  • one that stores the actual value.

This is very similar to the basic macros \title which is defined as

\def\title#1{\def\@title{#1}}
% or
\newcommand*{\title}[1]{\def\@title{#1}}

But (La)TeX doesn’t have the possibility to say \title{<something>} and if you use \title without an argument it gives you <something>.

But this basically is the nature of an .initial key.

References

7
  • That's not quite correct actually. See Claudio's answer. You need .get to extract the value from .initial. See the explanation in the manual for .get with red and blue. But I don't like the construction anyway. Probably it's a CS thingy that I don't understand.
    – percusse
    Aug 23, 2013 at 8:18
  • @percusse What specifically is “not quite correct”? I don’t say that you don’t need .get. Aug 23, 2013 at 8:23
  • The part with kind of wrong. That's strangely the recommended way by the TikZ team. And we have expansion control issues etc. So it's not that straightforward
    – percusse
    Aug 23, 2013 at 8:24
  • @percusse That “kind of wrong” describes the whole sequence of .initial, .get and .store in. The .get handler itself is useful (in a context that does not need to be expandable). Aug 23, 2013 at 8:28
  • Again, with .initial key you can't use the initial value. The manual has a blue and red example that shows what the key is promoted to. so you need to squeeze in .get there to initialize the macro used in /.store in. Otherwise you hit the error what Claudio shown with undefined macro. I've commented to him also about your suggestion but still it's not optimal.
    – percusse
    Aug 23, 2013 at 8:32
10

You can check the mechanism with the example below. get assigns the current value of the key to a macro and we are done. store in is instead keeps whatever argument is passed to the key itself.

\documentclass{article}
\usepackage{pgfkeys}

\begin{document}
\pgfkeys{a/.initial=1}
\pgfkeys{a/.get=\aKey}%

\aKey        %1
\pgfkeys{a=7}%
\aKey        %2
\pgfkeys{a}  %3
\aKey        %4
\pgfkeys{a/.get=\aKey}%
\aKey        %5

\par
\aKey        % Still 7
\pgfkeys{a/.store in=\aKey}
\pgfkeys{a=1}%
\aKey        % Now 1 Without 'get'ting

\end{document}

enter image description here

In your example you are getting the value of the key a to \aKey but then overwriting it with store in. If you remove the get part it will keep on working.

5
  • Indeed, removing the .get part works... And yet, I was pretty sure I had tried it before without success... strange!
    – remjg
    Aug 22, 2013 at 15:18
  • @remjg It's not strange but a little abused. The initial value is not directly available for use and that's what Claudio is explaining.
    – percusse
    Aug 22, 2013 at 15:46
  • Could you explain to me why \pgfkeys{a} displays something? Also, why does it display 7?
    – remjg
    Aug 23, 2013 at 14:49
  • 1
    I've read in an answer to the question When to use a regular .initial key or a .store in key? that pgfkeys{a} displays the content of the key if there is no handler .default to the key. I understand your example now!
    – remjg
    Aug 23, 2013 at 15:40
  • @remjg In the evening, I'll take another look. As Qrr mentioned, this is far from a satisfactory answer and needs some under the hood demo. Where is Ryan Reich when you need him?
    – percusse
    Aug 23, 2013 at 16:03
4

I also use this approach even if it is not the only possible with pgfkeys, see Qrrbrbirbel comment in Simple example of pgfkeys.

I would like to add a common-sense explanation to zeroth answer.

Assuming x be the initial value of the key key-x, thanks to the handler store in it is passed to the macro, say \macro@x. Usually, you want to use this macro somewhere and very likely you don't want to be forced to pass values to it every time. This because can be possible that the key-x uses x most of the times and it should change its value only few times. Now you can use \macro@x in your application being sure at the beginning it has x as initial value.

Suppose now to call your application passing to key-x another value, say y. One might think: now \macro@x should contain y. Well, that's not true. It becomes true only if you added the handler get to key-x, otherwise you will end up with errors.

As demonstration, look at the following example:

\documentclass{article}

\usepackage{tikz}

\pgfkeys{/tikz/.cd,
  N/.initial=10,
  N/.get=\N,
  N/.store in=\N,
}


\newcommand{\showN}[1][]{
\begin{tikzpicture}[#1]
\pgfmathtruncatemacro\m{\N/5}
\node{\m};
\end{tikzpicture}
}

\begin{document}
\showN
\showN[N=20]
\showN


\end{document}

This prints:

2 4 2

when the get handler is present, otherwise:

! Undefined control sequence.
<argument> \N
/5
l.21 \showN
[N=20]
The control sequence at the end of the top line
of your error message was never \def'ed. If you have
misspelled it (e.g., `\hobx'), type `I' and the correct
spelling (e.g., `I\hbox'). Otherwise just continue,
and I'll forget about whatever was undefined.

Just for reference, one may avoid completely the initial and get handlers with the following approach:

\def\N{10}%
\pgfkeys{/tikz/.cd,%
  N/.store in=\N,%
}%

By substituting this in the previous MWE, it is correctly printed:

2 4 2

As a matter of facts, you have seen there are several ways to achieve the same result: just the programming styles are different.

6
  • The problem is that the key is not set when you call it initially. Instead of using get, you can use default. But you need to call the key to make the initial assignment.
    – percusse
    Aug 22, 2013 at 15:32
  • Scratch that. I think I don't like the construction and complaining for no reason. Never mind my comment.
    – percusse
    Aug 22, 2013 at 15:51
  • @percusse: haha, no problems at all. :) Aug 22, 2013 at 17:56
  • Of course, without .get the \N macro is undefined because you do not initialize it even though you use .initial (which initialize a “value key” and nothing more). I may repeat myself, but don’t use .initial if you want to do .store in. Simply do N/.store in=\N, N=<initial value> (or the quicker \def\N{<initial value>). Even more so, there is still a “value key” present which you can access with \pgfkeysvalueof{/tikz/N} but it is in no relation to \N and cannot be set with N=<value>. You have defined now three macros: \pgfk@/tikz/N, \pgfk@/tikz/N/.@cmd and \N. Aug 23, 2013 at 9:53
  • @Qrrbrbirlbel: as I said in the last part of my answer, I believe this is more a matter of programming style. It's true that the "triple" procedure is not optimum, but one "should"/"would" care only if it he's developing a huge package. Then, this may lead to endless discussion as I prefer call \N rather than \pgfkeysvalueof{/tikz/N} for future code readability. But, you know, there lots of things to be traded (commodity in writing code, purpose of the code). Aug 23, 2013 at 10:25
4

Well the manual is actually pretty clear in the wording, your question is then targeted about the difference of \let and \def.

For a difference between \let and \def please see: What is the difference between \let and \def?

Might I also point to the attention of:

Key handler <key>/.estore in=<macro>

instead of \def as in .store in it executes an \edef.
For further reference on this topic see: What is the difference between \let and \edef?

The problem

You should not mix the usage of .store in and .get as they do the same thing differently.

The key .store in enables you to overcome the need for getting keys from pgfkeys by the use of a single macro.

By doing \pgfkeys{/a/.store in=\aKey} you will then always have \aKey be the value that is assigned. Note that \aKey is not a macro until a=<value> gets executed.

Take this example:

\newcommand{\showa}{a is \aKey}

% Try and switch between these two
\pgfkeys{a/.store in=\aKey}
%\pgfkeys{a/.get=\aKey}

\pgfkeys{a=1}
\showa
\pgfkeys{a=2}
\showa
\pgfkeys{a=3}
\showa

This will print:

a is 1 a is 2 a is 3

The first pgfkeys is simply to reference the value of a to \aKey. In effect each time a=<something> is done you actually do \def{\aKey}{<something>}. Hence this should only be performed once.

The .get will behave differently but can be used to achieve the same effect. However, certain cases where you need to control the expansion of \aKey will let you choose whichever case you prefer.

Your code

Your code should then be something like this:

\pgfkeys{a/.store in=\aKey}
\pgfkeys{a/.initial=1}
\newcommand{\DisplayKey}[1]{
    \pgfkeys{#1}
    a is \aKey
}
\DisplayKey{a=7}
\DisplayKey{a=3}

and it will print a is 7 a is 3.

4
  • No worries, I'm currently reading the \let, \def, \edef explanations you gave me as a link... I still have many things to learn!
    – remjg
    Aug 22, 2013 at 15:07
  • You said that The .get will behave almost the same (in the above example the same). Actually, since the \let instruction (induced by the .get handler) is done before the key a is defined, the resulting macro \aKey is empty. Here is the output I get: a is a is a is
    – remjg
    Aug 23, 2013 at 15:07
  • @remjg I don't know why i wrote that, I am sorry. I will delete it from my test example! Sorry for my late response!
    – nickpapior
    Oct 3, 2013 at 19:59
  • no worries, I've learned a lot thanks to you anyway!
    – remjg
    Oct 4, 2013 at 7:10
2

Well, I'm not going to give an answer to my question, but just practical examples to observe the behaviour of the key handlers .get and .store in. Your answers helped me a lot but I needed a good night of sleep to set things in order and these examples to be able to try different configurations.

Since setting an initial value (handler .initial) and a default value (handler .default) is often a related problem, I also want to write here some details I've gathered:

  • if there is a default value: pgfkeys{a} will set the default value to the key a
  • if there is no default value: pgfkeys{a} displays the value of the key a

Examples with the .get handler

I have used a default value in the examples of this section to avoid displaying twice the key a when calling \DisplayKey{a}.

Each time, I've generated two outputs: the one on the right corresponds to the case where an initial value of 0 is used for the key a.

Example 1

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{/a/.default=1}
\pgfkeys{/a/.initial=0} % uncomment for image on the right    

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{/a/.get=\aKey}% .get before setting key a
  \pgfkeys{#1}%
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

.get before setting the key .get before setting the key with initial value

Example 2

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{/a/.default=1}
\pgfkeys{/a/.initial=0} % uncomment for image on the right

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{#1}%
  \pgfkeys{/a/.get=\aKey}% .get after setting key a
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

.get after setting the key .get after setting the key with initial value

Example 3

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{/a/.default=1}
\pgfkeys{/a/.initial=0} % uncomment for image on the right
\pgfkeys{/a/.get=\aKey}% .get before every setting operation to the key

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{#1}%
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

.get at the beginning before any setting operation to the key .get at the beginning before any setting operation to the key with initial value

Examples with the .store in handler

I have used an initial value of 0 in every examples of this section. Indeed, the macro \aKey doesn't exist until a is set for the first time (\DisplayKey{} doesn't set a but asks for \aKey so it needs to be defined before).

Each time, I've generated two outputs: the one on the right corresponds to the case where an default value of 1 is used for the key a.

Example 4

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{
  /a/.default=1, % uncomment to get image on the right
  /a/.store in=\aKey, % .store in at the beginning before any setting operation to the key
  a=0} % set a, calls .store in and defines \aKey (otherwise \DisplayKey{} would produce an error)

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{#1}%
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

.store in at the beginning before any setting operation to the key .store in at the beginning before any setting operation to the key with default value

Example 5 (bad)

And here is what I was doing...

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{
  /a/.default=1, % uncomment to get image on the right
  /a/.initial=0,
  /a/.get=\aKey, % if you remove it, \DisplayKey{} generates an error (\aKey not defined)
  /a/.store in=\aKey} % \aKey will be redefined each time a is set

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{#1}%
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

a bad way of doing things a bad way of doing things with default value 1

Bonus

I also want to mention another solution which makes use of the handler .code and the macros \pgfkeyssetvalue and \pgfkeysgetvalue. Indeed, it makes things easy to test weather a key has been set.

\documentclass[varwidth,margin=0.5cm]{standalone}
\usepackage{pgfkeys}

\pgfkeys{
  /a/.default=1, % uncomment to get image on the right
  /a/.code={\pgfkeyssetvalue{a}{#1}\pgfkeysgetvalue{a}{\aKey}},
  a=0}

\newcommand{\DisplayKey}[1]{%
  \pgfkeys{#1}%
  \aKey}%

\begin{document}
  a / value stored in \textbackslash aKey\par
  ? / \DisplayKey{}\par
  1 / \DisplayKey{a}\par
  2 / \DisplayKey{a=2}\par
  3 / \DisplayKey{a=3}\par
  4 / \DisplayKey{a=4}\par
\end{document}

Using \pgfkeyssetvalue and \pgfkeysgetvalue Using \pgfkeyssetvalue and \pgfkeysgetvalue with a defaut value

You must log in to answer this question.

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