为变量赋值并检索以供日后使用的推荐方法是什么?

为变量赋值并检索以供日后使用的推荐方法是什么?

在文档内定义变量并稍后检索其值的推荐方法是什么?

我在 Google 上搜索了几种不同的解决方案,通常大约 10 行。我想知道,一定有一种更短的方法来做这样的事情(伪代码):

\setvalue(VARIABLE1){foo foo bar}

并在文档后面

$\getvalue(VARIABLE1)$.

我也见过一些解决方案,包括定义一个新命令,但如果该命令已经在另一个包中使用了怎么办?这似乎不是一个独立的解决方案。

答案1

好吧,我知道这不是你想要的,但标准路线是使用 或defnewcommand你接触到的问题是全局命名空间。如果你使用newcommand它会告诉你命令是否已经设置(作为编译中的错误,将命名违规newcommand尝试),保护你免受这些问题的影响。

% Set your new variable. In this case it will be 
% called "\MyNewVariable" and the value will be "hello".
\newcommand{\MyNewVariable}{hello}

% Use to get the variable.
\MyNewVariable

如果您可以将自己的姓名或其他助记符添加到所有名称前面,则不太可能发生冲突。然后,此助记符将充当您自己的(某种)命名空间。

假设您的变量的第一个实例是用 a 设置的newcommand而没有引发错误,那么 arenewcommand可用于稍后更改该变量。

答案2

听起来您正在寻找一个键值系统。我可以建议吗pgfkeys?包括 Yiannis 为每个变量使用属性的想法,我会这样做:

\documentclass{article}
\usepackage{pgfkeys}

\newcommand{\setvalue}[1]{\pgfkeys{/variables/#1}}
\newcommand{\getvalue}[1]{\pgfkeysvalueof{/variables/#1}}
\newcommand{\declare}[1]{%
 \pgfkeys{
  /variables/#1.is family,
  /variables/#1.unknown/.style = {\pgfkeyscurrentpath/\pgfkeyscurrentname/.initial = ##1}
 }%
}

\declare{}

\begin{document}
 \setvalue{VARIABLE1 = foo foo bar}
 \getvalue{VARIABLE1}

 \declare{test/}
 \setvalue{test/property = 12}
 \getvalue{test/property}
\end{document}

不到十行,即使算上只有括号的行。操作非常简单:pgfkeys将变量作为“文件”存储在“目录”中;我决定你的变量应该在目录中/variables,所以不是在全局命名空间中。(顺便说一句,pgfkeys键永远不会与普通宏名称冲突,因此它的“全局命名空间”与宏命名空间不同。)

\setvalue只是适当地更改目录,然后调用您的分配。宏\getvalue从正确的目录中检索变量。

唯一的技巧是,在 中pgfkeys,键需要在分配之前“已知”,否则您必须将其调用为key/.initial = value。由于我不想强迫您编写它,因此我为未知变量创建了一个“处理程序”,只需在后台添加这一段代码即可。

您可以使用 声明一个具有属性的变量\declare{variable/},然后可以variable/property在中用作变量名\setvalue(您也可以用作variable/默认目录,因此写

\setvalue{variable, property 1 = value 1, property 2 = value 2}

这很方便)。该\declare宏只是为“目录”设置了未知的处理程序/variables/variable/(这意味着\declare{}开头的神秘行设置了/variables/目录本身)。

答案3

我宁愿使用某种 Lisp 方式或面向对象的方式来定义它们。

在下面的最小示例中,我们使用:

\setproperty{test}{aproperty}{12}
\getproperty{test}{aproperty}

将它们视为代表test.aproperty(我们实际上将它们定义为test@paproperty),这样它就不太可能与任何现有命令发生冲突,除了您自己的命令:

最小的:

\documentclass{article}
\makeatletter
%  Properties a la Lisp.
\def\ece#1#2{\expandafter#1\csname#2\endcsname}%
% \setproperty{ATOM}{PROPNAME}{VALUE} defines the property PROPNAME on the
% ``atom'' ATOM to have VALUE.
% 
\def\setproperty#1#2#3{\ece\protected@edef{#1@p#2}{#3}}%
\def\setpropertyglobal#1#2#3{\ece\protected@xdef{#1@p#2}{#3}}%
%
% 
% \getproperty{ATOM}{PROPNAME} expands to the value of the property
% PROPNAME on ATOM, or to nothing (i.e., \empty), if the property isn't
% present.
% 
\def\getproperty#1#2{%
  \expandafter\ifx\csname#1@p#2\endcsname\relax
  % then \empty
  \else \csname#1@p#2\endcsname
  \fi
}%
%
\makeatother

\begin{document}
\setproperty{test}{aproperty}{12}
\getproperty{test}{aproperty}
\end{document}

答案4

您的代码几乎是有效的 ConTeXt:您使用定义一个变量

\setvalue{variable1}{value}

并可以使用获取其值

\getvalue{variable1}

(这些类似于LaTeX 中的\@namedef\@nameuse)。如果您想要键值驱动的变量,您可以使用:

\definenamespace
    [VAR]
    [
      name=VAR,
      setup=list,
      command=list,
      parent=VAR,
    ]

\setupVAR
    [a={default A},
     b={default B}]

\defineVAR
    [set1]
    [a={set1 A},
     c={set1 C}]

\defineVAR
    [set2]
    [b={set2 B},
     c={set2 C}]

\starttext
\startlines
  \namedVARparameter{set1}{a} % gives set1 A
  \namedVARparameter{set1}{b} % gives default B
  \namedVARparameter{set1}{c} % gives set1 C
\stoplines
\stoptext

相关内容