
在文件中定義變數並稍後檢索其值的建議方法是什麼?
我用谷歌搜尋了幾種不同的解決方案,通常大約有 10 行長。我想知道,一定有一種更短的方法來做這樣的事情(偽代碼):
\setvalue(VARIABLE1){foo foo bar}
以及稍後在文件中
$\getvalue(VARIABLE1)$.
我還看到過包括定義新命令的解決方案,但是如果該命令已在另一個包中使用怎麼辦?這看起來並不是一個獨立的解決方案。
答案1
好吧,我知道這不是您想要的,但標準路線是帶有 adef
或 a newcommand
。您提到的問題是全域名稱空間。如果您使用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
如果您可以在它們前面加上您的名字或其他助記符,那麼您就不太可能發生衝突。然後,該助記符將充當您自己的(某種)命名空間。
假設變數的第一個實例設定為 anewcommand
且不會引發錯誤,則renewcommand
稍後可以使用 a 來變更該變數。
答案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
(我們實際上將它們定義為 a 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}
\@namedef
(這些與 LaTeX 中的和類似\@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