¿Cuál es la forma recomendada de asignar un valor a una variable y recuperarlo para su uso posterior?

¿Cuál es la forma recomendada de asignar un valor a una variable y recuperarlo para su uso posterior?

¿Cuál es la forma recomendada de definir una variable dentro de un documento y recuperar su valor más adelante?

Busqué en Google varias soluciones diferentes, generalmente de unas 10 líneas de largo. Me preguntaba si debe haber una forma más corta de hacer algo como esto (pseudocódigo):

\setvalue(VARIABLE1){foo foo bar}

y más adelante en el documento

$\getvalue(VARIABLE1)$.

También he visto soluciones que incluyen la definición de un nuevo comando, pero ¿qué pasa si ese comando ya se usa dentro de otro paquete? Realmente no parece una solución independiente.

Respuesta1

Bueno, sé que no es lo que quieres, pero la ruta estándar es con a defo a newcommand. El problema que has mencionado es el espacio de nombres global. Si lo usa, newcommandle indicará si el comando ya está configurado (como un error en la compilación que indicará el newcommandintento ofensivo), protegiéndolo de estos problemas.

% 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

Si pudiera anteponerlos a todos con su nombre o algún otro mnemotécnico, entonces es poco probable que haya conflictos. Este mnemónico luego se comporta como su propio (más o menos) espacio de nombres.

Suponiendo que la primera instancia de su variable está configurada con a newcommandsin generar un error, entonces a renewcommandse puede usar para modificar esa variable más adelante.

Respuesta2

Parece que estás buscando un sistema clave-valor. Puedo sugerir pgfkeys? Incluyendo la idea de Yiannis de usar propiedades para cada variable, lo haría así:

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

Menos de diez líneas, incluso contando las que sólo tienen llaves. El funcionamiento es muy sencillo: pgfkeysalmacena variables como "archivos" en "directorios"; He decidido que el tuyo debería estar en el/variables directorio, así quenoen el espacio de nombres global. (Por cierto, pgfkeyslas claves nunca entran en conflicto con los nombres de macros normales, por lo que su "espacio de nombres global" es diferente del espacio de nombres de las macros).

La \setvaluemacro simplemente cambia de directorio apropiadamente y luego llama a su tarea. La \getvaluemacro recupera la variable del directorio correcto.

El único truco es que en pgfkeys, es necesario "conocer" una clave antes de asignarla; de lo contrario, debe llamarla como key/.initial = value. Como no quiero obligarte a escribir eso, creé un "controlador" para variables desconocidas que simplemente agrega este fragmento de código detrás de escena.

Declaras una variable con propiedades usando \declare{variable/}, y luego puedes usarla variable/propertycomo nombre de variable en \setvalue(también puedes usarla variable/como directorio predeterminado, así que escribe

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

lo cual es conveniente). La \declaremacro simplemente configura el controlador desconocido para el "directorio" /variables/variable/(lo que significa que la línea críptica \declare{}al principio configura el /variables/directorio en sí).

Respuesta3

Prefiero definirlos usando una especie de método Lisp u orientado a objetos.

En el mínimo a continuación, utilizamos:

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

Piense en ellos como representativos test.aproperty(en realidad los definimos como test@paproperty), de esta manera es muy poco probable que entren en conflicto con algún comando existente, excepto posiblemente el suyo:

Lo mínimo:

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

Respuesta4

Tu código es casi válido ConTeXt: defines una variable usando

\setvalue{variable1}{value}

y puede obtener su valor usando

\getvalue{variable1}

(Estos son similares a \@namedefy \@nameuseen LaTeX). Si desea variables basadas en valores clave, puede utilizar:

\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

información relacionada