Какой рекомендуемый способ присвоения значения переменной и извлечения его для последующего использования?

Какой рекомендуемый способ присвоения значения переменной и извлечения его для последующего использования?

Какой рекомендуемый способ определения переменной внутри документа и последующего извлечения ее значения?

Я гуглил несколько разных решений, обычно длиной около ~10 строк. Мне было интересно, должен ли быть более короткий способ сделать что-то вроде этого (Псевдокод):

\setvalue(VARIABLE1){foo foo bar}

и далее в документе

$\getvalue(VARIABLE1)$.

Я также видел решения, которые включают определение новой команды, но что, если эта команда уже используется внутри другого пакета? Это не похоже на независимое решение.

решение1

Ну, я знаю, что это не то, что вам нужно, но стандартный маршрут — либо с a, defлибо с 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

Если бы вы могли предварять их все своим именем или какой-то другой мнемоникой, то вряд ли у вас будут конфликты. Эта мнемоника затем ведет себя как ваше собственное (своего рода) пространство имен.

Если предположить, что первый экземпляр вашей переменной установлен с помощью a newcommandбез возникновения ошибки, то a renewcommandможно использовать для изменения этой переменной позже.

решение2

Похоже, вы ищете систему ключ-значение. Могу ли я предложить pgfkeys? Включая идею Янниса об использовании свойств для каждой переменной, я бы сделал это так:

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

(Они похожи на \@namedefи \@nameuseв LaTeX). Если вам нужны переменные, управляемые ключом-значением, вы можете использовать:

\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

Связанный контент