![对在 foreach 循环中更新 newcommand 常量感到困惑](https://linux22.com/image/437543/%E5%AF%B9%E5%9C%A8%20foreach%20%E5%BE%AA%E7%8E%AF%E4%B8%AD%E6%9B%B4%E6%96%B0%20newcommand%20%E5%B8%B8%E9%87%8F%E6%84%9F%E5%88%B0%E5%9B%B0%E6%83%91.png)
我对如何更新 \foreach 循环内的“常量”构造感到困惑,这里的类似问题并没有直接解决我所面临的问题,而且我还没有在 LaTeX 中进行足够的实验(还没有!;)来自己解决这个问题。
我认为问题出在 \const 定义上。我曾尝试用 \glet、\csglet、\gletcs 和 \csgletcs 替换 \global\edef(相当盲目,但这里的几个答案中都建议这样做),但无济于事。
我很感激任何关于此事的帮助,
谢谢!
\documentclass{article}
\usepackage{pgffor}
\usepackage[nomessages]{fp}
% ---- Helper function: easily add values to variables
% Taken from a reply on stackoverflow that I can't find back...
%. Works like so \const{VariableName}{value} ex: \const{CoolVariable}{5}
%. and can then be called with \CoolVariable
%. and can be updates with \const{CoolVariable}{CoolVariable+10}
\newcommand\const[3][0]{%
\global\edef\temporary{round(#3}%
\expandafter\FPeval\csname#2\expandafter\endcsname
\expandafter{\temporary:#1)}%
}
% ---- Set dummy variable
\const{MyVariable}{1}
% ---- I want to loop over a list of keywords with the name of "MyVariable"
%. Only one here for example.
\newcommand\MyVariableList{MyVariable}
% ---- Start the loop and update values of constants in MyVariableList
\foreach \variable in \MyVariableList{
% ---- This updates the variable \MyVariable correctly
\const{\csname variable\endcsname}{\csname variable\endcsname +20}
% ---- Values of \MyVariable changes within the loop
MyVariable inside the loop: \csname \variable\endcsname
}
\begin{document}
MyVariable outisde the loop:
% ---- But not outside of it
\MyVariable
\end{document}
答案1
\foreach
将每次迭代放在一个组中。因此,您需要将变量的赋值设为全局变量。
以下用途xfp
(因为我不知道如何使用来实现这一点fp
)使分配变得全局化。
\documentclass{article}
\usepackage{pgffor}
\usepackage{xfp}
\newcommand\const[3][0]{%
\xdef#2{\fpeval{round(#3,#1)}}%
}
% ---- Set dummy variable
\const\MyVariable{1}
% ---- I want to loop over a list of keywords with the name of "MyVariable"
%. Only one here for example.
\newcommand\MyVariableList{MyVariable}
\begin{document}
% ---- Start the loop and update values of constants in MyVariableList
\foreach \variable in \MyVariableList{%
% ---- This updates the variable \MyVariable correctly
\expandafter\const\csname\variable\endcsname{\csname\variable\endcsname +20}%
% ---- Values of \MyVariable changes within the loop
MyVariable inside the loop: \csname\variable\endcsname
}
MyVariable outside the loop:
% ---- But not outside of it
\MyVariable
\end{document}
另一种方法是使用不对迭代进行分组的循环。可以使用以下方法完成此操作\clist_map_inline:nn
:
\documentclass{article}
% get the function from expl3 and give it a document level name so that we can
% use it.
\ExplSyntaxOn
\cs_new_eq:NN \clistmap \clist_map_inline:nn
\ExplSyntaxOff
\usepackage[nomessages]{fp}
% ---- Helper function: easily add values to variables
% Taken from a reply on stackoverflow that I can't find back...
%. Works like so \const{VariableName}{value} ex: \const{CoolVariable}{5}
%. and can then be called with \CoolVariable
%. and can be updates with \const{CoolVariable}{CoolVariable+10}
\newcommand\const[3][0]{%
\edef\temporary{round(#3}%
\expandafter\FPeval\csname#2\expandafter\endcsname
\expandafter{\temporary:#1)}%
}
% ---- Set dummy variable
\const{MyVariable}{1}
\const{YourVariable}{2}
\begin{document}
% ---- Start the loop and update values of constants in MyVariableList
\clistmap{MyVariable, YourVariable}
{%
% #1 will be the current loop iterations element
% ---- This updates the variable \MyVariable correctly
\const{#1}{#1 + 20}%
% ---- Values of \MyVariable changes within the loop
#1 inside the loop: \csname #1\endcsname\par
}
MyVariable outside the loop:
% ---- But not outside of it
\MyVariable
\YourVariable
\end{document}
答案2
\foreach
每个循环都在一个组内进行。这是一个很常见的问题。
你可以\global\edef
始终对常量进行全局赋值。顺便说一句,代码中的使用是多余的。
\documentclass{article}
\usepackage{pgffor}
\usepackage[nomessages]{fp}
% ---- Helper function: easily set values to variables
\newcommand\const[3][0]{%
\FPeval\temporary{round(#3:#1)}%
\global\expandafter\let\csname #2\endcsname\temporary
}
% ---- Set dummy variable
\const{MyVariable}{1}
% ---- I want to loop over a list of keywords with the name of "MyVariable"
%. Only one here for example.
\newcommand\MyVariableList{MyVariable}
\begin{document}
% ---- Start the loop and update values of constants in MyVariableList
\foreach \variable in \MyVariableList{
% ---- This updates the variable \MyVariable correctly
\const{\csname variable\endcsname}{\csname variable\endcsname +20}
% ---- Values of \MyVariable changes within the loop
MyVariable inside the loop: \csname \variable\endcsname
}
MyVariable outside the loop:
% ---- But not outside of it
\MyVariable
\end{document}
我在这里展示了一种不同的方法,其中变量“按名称”调用,而不是使用笨拙的\csname<name>\endcsname
。
\documentclass{article}
\usepackage{xfp} % easier than fp
\ExplSyntaxOn
\NewDocumentCommand{\const}{O{0}mm}
{
% allocate a variable if not yet existing
\fp_if_exist:cF { l_pimento_const_#2_fp }
{ \fp_new:c { l_pimento_const_#2_fp } }
% set the value
\fp_set:cn { l_pimento_const_#2_fp } { round(#3,#1) }
}
\NewExpandableDocumentCommand{\eval}{m}
{
\fp_use:c { l_pimento_const_#1_fp }
}
\NewDocumentCommand{\setconstants}{sO{0}mm}
{
\cs_set:Nn \__pimento_const_set:n { \const[#2]{##1}{#4} }
\IfBooleanTF{#1}
{
\clist_map_function:NN #3 \__pimento_const_set:n
}
{
\clist_map_function:nN { #3 } \__pimento_const_set:n
}
}
\ExplSyntaxOff
% ---- Set dummy variable
\const{MyVariableA}{1}
\const{MyVariableB}{3}
\newcommand{\MyList}{MyVariableA,MyVariableB}
\begin{document}
\setconstants{MyVariableA,MyVariableB}{\eval{#1}+20}
\eval{MyVariableA}
\eval{MyVariableB}
\setconstants*[2]{\MyList}{\eval{#1}/2}
\eval{MyVariableA}
\eval{MyVariableB}
\fpeval{\eval{MyVariableA}+\eval{MyVariableB}}
\end{document}
其最大的优势在于fp
操作可扩展。