
Was ist die empfohlene Methode, um eine Variable in einem Dokument zu definieren und ihren Wert später abzurufen?
Ich habe mehrere verschiedene Lösungen gegoogelt, die normalerweise etwa 10 Zeilen lang sind. Ich fragte mich, ob es einen kürzeren Weg geben muss, so etwas zu tun (Pseudocode):
\setvalue(VARIABLE1){foo foo bar}
und später im Dokument
$\getvalue(VARIABLE1)$.
Ich habe auch Lösungen gesehen, die das Definieren eines neuen Befehls beinhalten, aber was ist, wenn dieser Befehl bereits in einem anderen Paket verwendet wird? Das scheint nicht wirklich eine unabhängige Lösung zu sein.
Antwort1
Nun, ich weiß, dass es nicht das ist, was Sie wollen, aber die Standardroute ist entweder mit a def
oder a newcommand
. Das Problem, das Sie angesprochen haben, ist der globale Namespace. Wenn Sie newcommand
ihn verwenden, wird Ihnen mitgeteilt, ob der Befehl bereits festgelegt ist (als Kompilierungsfehler, der den fehlerhaften newcommand
Versuch benennt), und Sie sind so vor diesen Problemen geschützt.
% 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
Wenn Sie allen Ihren Namen oder eine andere Eselsbrücke voranstellen könnten, wäre es unwahrscheinlich, dass es zu Konflikten kommt. Diese Eselsbrücke verhält sich dann wie Ihr eigener (Art) Namespace.
Vorausgesetzt, dass die erste Instanz Ihrer Variable mit einem festgelegt wird, newcommand
ohne dass ein Fehler auftritt, renewcommand
kann ein verwendet werden, um diese Variable später zu ändern.
Antwort2
Klingt, als ob Sie nach einem Schlüssel-Wert-System suchen. Darf ich vorschlagen pgfkeys
? Unter Berücksichtigung von Yiannis‘ Idee, Eigenschaften für jede Variable zu verwenden, würde ich es folgendermaßen machen:
\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}
Weniger als zehn Zeilen, selbst wenn man die mit Klammern mitzählt. Die Operation ist sehr einfach: pgfkeys
speichert Variablen als „Dateien“ in „Verzeichnissen“; ich habe entschieden, dass Ihre im Verzeichnis sein sollten /variables
, alsonichtim globalen Namespace. (Übrigens pgfkeys
stehen Schlüssel nie im Konflikt mit normalen Makronamen, daher unterscheidet sich sein „globaler Namespace“ vom Namespace der Makros.)
Das \setvalue
Makro wechselt einfach entsprechend das Verzeichnis und ruft dann Ihre Zuweisung auf. Das \getvalue
Makro ruft die Variable aus dem richtigen Verzeichnis ab.
Der einzige Trick besteht darin pgfkeys
, dass in ein Schlüssel „bekannt“ sein muss, bevor er zugewiesen wird, sonst müssen Sie ihn als aufrufen key/.initial = value
. Da ich Sie nicht zwingen möchte, das zu schreiben, habe ich einen „Handler“ für unbekannte Variablen erstellt, der diesen Codeabschnitt einfach im Hintergrund hinzufügt.
Sie deklarieren eine Variable mit Eigenschaften mit \declare{variable/}
und können dann variable/property
als Variablennamen in verwenden \setvalue
(Sie können auch variable/
als Standardverzeichnis verwenden, schreiben Sie also
\setvalue{variable, property 1 = value 1, property 2 = value 2}
was praktisch ist). Das \declare
Makro richtet einfach den unbekannten Handler für das „Verzeichnis“ ein /variables/variable/
(was bedeutet, dass die kryptische Zeile \declare{}
am Anfang das Verzeichnis selbst einrichtet /variables/
).
Antwort3
Ich würde sie lieber auf eine Art Lisp- oder objektorientierte Weise definieren.
Im Folgenden verwenden wir:
\setproperty{test}{aproperty}{12}
\getproperty{test}{aproperty}
Betrachten Sie sie als Darstellungen test.aproperty
(wir definieren sie eigentlich als test@paproperty
). Auf diese Weise ist es höchst unwahrscheinlich, dass es zu Konflikten mit vorhandenen Befehlen kommt, außer möglicherweise mit Ihren eigenen:
Das Minimale:
\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}
Antwort4
Ihr Code ist fast gültiger ConTeXt: Sie definieren eine Variable mit
\setvalue{variable1}{value}
und kann seinen Wert erhalten durch
\getvalue{variable1}
(Diese sind ähnlich zu \@namedef
und \@nameuse
in LaTeX). Wenn Sie schlüsselwertgesteuerte Variablen möchten, können Sie Folgendes verwenden:
\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