pgfkeys 密钥处理程序 .get 和 .store 起什么作用?

pgfkeys 密钥处理程序 .get 和 .store 起什么作用?

当我需要检索宏中某个键的值时,我会使用键处理程序.get.store in。以下是鍵盤文档:

密钥处理程序 key/.get= macro 执行\let命令,以便宏包含存储在 key 中的内容。

键处理程序 key/.store in= macro 此处理程序具有以下效果:当您写入 时key = value,将执行代码\def macro { value }。因此,给定的值被“存储”在宏 中。

我不太明白这两个处理程序之间的区别。实际上,我本来以为它们.store in就足够了,但我却需要两者。为什么?

代码

下面通常是我使用时写的内容(不理解它......)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}

输出

在此处输入图片描述

答案1

三个答案却带来更多困惑(至少我是这样)。


处理程序.get非常.store in不同,没有任何相似之处。

<key>/.store in=\<macro>处理程序设置一个键<key>,以便如果它与<key>=<value>它一起使用,它将存储<value>在中\<macro>。这与您写的一样<key>/.code=\def\<macro>{#1}

每次使用时,<key>\<macro>都会被重新定义。

处理.get程序实际上执行的是相反的操作,它获取密钥的当前值并将其存储在宏中。未授权的.initial密钥将返回\relax

处理程序.get只是通过易于使用的宏接收键值的众多方法之一。(请记住,键本身也只是一个宏。)\pgfkeysgetvalue{/full/path to/key}\<macro>如果您不需要宏,其他方法包括 或\pgfkeysvalueof{/full/path to/key}


你用什么

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

这是一种不好的做法,因为你首先将键设置为“值键”,并用值初始化它1。然后你获取它1并将其保存在\aKey(这实际上是一个,\let但这并不重要)。然后你将键的设置更改为一个.store in键,一个将其值保存在宏中的键。这与前一个键无关.initial

这相当于

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

可以看出这\aValue没有什么实际用途。实际上你使用了三个宏:

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

也可以通过以下方式实现

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

或者

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

或者在 PGFkeys 中:

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

正如之前所讨论的何时使用常规 .initial 键或 .store in 键?,我认为.store in已经过时了,因为每个键都需要两个宏:

  • \def一个用于执行和的密钥本身
  • 一个存储实际值。

这与基本宏非常相似,\title其定义为

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

但是 (La)TeX 没有能力说出\title{<something>},如果你\title不带参数地使用,它会给你<something>

但这基本上是钥匙的本质.initial

参考

答案2

您可以使用下面的示例检查该机制。get将键的当前值分配给宏,我们就完成了。store in而是保留传递给键本身的任何参数。

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

在此处输入图片描述

在您的示例中,您获取了键的值a\aKey然后用 覆盖了它store in。如果您删除该get部分,它将继续工作。

答案3

我也使用这种方法,即使它不是唯一可行的方法pgfkeys,请参阅魁北克评论pgfkeys 的简单示例

我想补充一个常识性的解释第零个回答。

假设X是键的初始值key-x,这要归功于store in传递给宏的处理程序,例如\macro@x。通常,您希望在某个地方使用此宏,并且很可能您不想每次都被迫向其传递值。这是因为key-x使用X大多数情况下,它应该只会改变几次其值。现在您可以\macro@x在应用程序中使用它,确保在开始时它具有X作为初始值。

假设现在调用应用程序并传递给key-x另一个值,比如说y。有人可能会想:现在\macro@x应该包含y。嗯,事实并非如此。只有将处理程序添加get到后,它才会变为真key-x,否则您将最终得到错误。

作为演示,请看以下示例:

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

这将打印:

2 4 2

get处理程序存在时,否则:

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

仅供参考,可以采用以下方法完全避免initial和处理程序:get

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

通过在前一个 MWE 中替换它,可以正确打印:

2 4 2

事实上,您已经看到,有几种方法可以实现相同的结果:只是编程风格不同。

答案4

好吧,我不会回答我的问题,只是给出一些实际的例子来观察密钥处理程序的行为.get.store in您的回答对我帮助很大,但我需要一晚的睡眠来理清事情,并利用这些例子来尝试不同的配置。

由于设置初始值(处理程序.initial)和默认值(处理程序.default)通常是一个相关问题,因此我也想在这里写下一些我收集的细节:

  • 如果有默认值:pgfkeys{a}将默认值设置为键a
  • 如果没有默认值:pgfkeys{a}显示键的值a

.get处理程序示例

我在本节的示例中使用了默认值,以避免a在调用时显示两次键\DisplayKey{a}

每次我都会生成两个输出:右边的输出对应于初始值其中 0 用于 键a

示例 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 之前设置初始值的键

示例 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}

设置密钥后获取 设置初始值的键后获取

示例 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 在对具有初始值的键进行任何设置操作之前,先在开头获取.get

.store in处理程序示例

我在本节的每个示例中都使用了 0 作为初始值。事实上,宏只有在第一次设置\aKey时才存在(未设置但要求设置,因此需要事先定义)。a\DisplayKey{}a\aKey

每次我都会生成两个输出:右边的输出对应于默认值其中 1 用于 键a

示例 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

示例 5(错误)

这就是我当时做的事情...

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

做事方式不好 使用默认值 1 的糟糕做法

奖金

我还想提一下另一种解决方案,它利用了处理程序.code和宏\pgfkeyssetvalue\pgfkeysgetvalue。事实上,它使事情变得容易测试是否已设置密钥

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

使用 \pgfkeyssetvalue 和 \pgfkeysgetvalue 使用带有默认值的 \pgfkeyssetvalue 和 \pgfkeysgetvalue

相关内容