当我需要检索宏中某个键的值时,我会使用键处理程序.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}
示例 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}
.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}
示例 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}
奖金
我还想提一下另一种解决方案,它利用了处理程序.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}