pgf 中的局部变量与全局变量,与 foreach 的交互

pgf 中的局部变量与全局变量,与 foreach 的交互

我正在尝试编写一个具有可变输入数量的宏(这对我很重要),该宏应返回不同输入的最大长度。它使用foreach以下宏pgffor

\documentclass{article}

\usepackage{pgffor}
%\usepackage{pgfpages}

\newcommand{\getmaxlength}[1]{%
    \newlength{\Lmax}
    \newlength{\Lcurr}
    \setlength{\Lmax}{0pt}
    \foreach \arg in {#1} {%
        Previous max: \the\Lmax\par
        \settowidth{\Lcurr}{\arg}
        \ifdim \Lcurr>\Lmax \global\setlength{\Lmax}{\Lcurr} \fi
        \arg\ is of length \the\Lcurr\par
        New max: \the\Lmax\par
    }
}

\begin{document}
\getmaxlength{A,AAA,AA}
\end{document}

在这个玩具示例中,其效果符合预期:

    Previous max: 0.0pt
    A is of length 7.50002pt
    New max: 7.50002pt
    Previous max: 7.50002pt
    AAA is of length 22.50005pt
    New max: 22.50005pt
    Previous max: 22.50005pt
    AA is of length 15.00003pt
    New max: 22.50005pt

但是,这个解决方案既不干净,也不强大:

  • 它需要在第 13 行进行global分配。我通过反复试验发现了这一点,但我认为它并不干净,而且我不知道副作用。
  • 如果我取消注释第 4 行,宏就会崩溃\usepackage(pgfpages),这进一步表明它可能做错了什么。

在任一情况下(删除global关键字,使用包pgfpages),我都会获得一种行为,其中 Lmax 在每次循环重复时重置:

    Previous max: 0.0pt
    A is of length 7.50002pt
    New max: 7.50002pt
    Previous max: 0.0pt
    AAA is of length 22.50005pt
    New max: 22.50005pt
    Previous max: 0.0pt
    AA is of length 15.00003pt
    New max: 15.00003pt

我认为这与处理局部变量和全局变量的方式有关foreach,而一个潜在的解决方案在于使用其remember选项(看这里)。但是我无法让它工作。(还要记住,Lmax 不是一个“经典”变量,而是一个长度多变的)。

那么,使我的代码能够有效解决这些问题的最简洁的方法是什么?

(顺便说一下,用例如下:我正在尝试为投影仪方程式构建一个“本地叠加”命令(例如,在方程式中将 x(x + 1)更改为 x^2 + x),该命令将遵循所有叠加的固定宽度,以便更加清晰可见。)

答案1

\global\setlength失败的原因pdfpages如下

  1. 此包加载calc
  2. 如果calc没有加载,\global\setlength则会意外运行。

我建议采用不同的方法,避免全局设置。宏\getmaxlength有一个可选参数,它应该是包装结果维度的东西,默认情况下只显示值。

\documentclass{article}

\ExplSyntaxOn

%% define a command with 
%% 1. optional argument #1 and default value \dim_eval:n
%% 2. mandatory argument #2 (which should be a comma separated list
%% The command just transfer the action to the internal function
\NewDocumentCommand{\getmaxlength}{ O{\dim_eval:n} m }
 {
  \howier_getmaxlength:nn { #1 } { #2 }
 }

%% allocate variables of type dimension and box
\dim_new:N \l_howier_getmaxlength_max_dim
\box_new:N \l__howier_getmaxlength_temp_box

%% the main function
\cs_new_protected:Nn \howier_getmaxlength:nn
 {
  % set the value to zero to start
  \dim_zero:N \l_howier_getmaxlength_max_dim
  % map over the list given as second argument, using one item at a time
  \clist_map_function:nN { #2 } \__howier_getmaxlength_do:n
  % use the final value (by default #1 would be \dim_eval:n)
  #1 { \l_howier_getmaxlength_max_dim }
 }

%% the auxiliary function taking as argument each item in the list
\cs_new_protected:Nn \__howier_getmaxlength_do:n
 {
  % store the current list item in a box so we can access to its width
  \hbox_set:Nn \l__howier_getmaxlength_temp_box { #1 }
  % set the dimension variable to the maximum between the previous
  % value and the width of the current item
  \dim_set:Nn \l_howier_getmaxlength_max_dim
   {
    \dim_max:nn { \l_howier_getmaxlength_max_dim } { \box_wd:N \l__howier_getmaxlength_temp_box }
   }
 }

\ExplSyntaxOff

\begin{document}

\getmaxlength{A,AAA,AA}

XAAAX

X\getmaxlength[\hspace]{A,AAA,AA}X

AAAX

\getmaxlength[\hspace*]{A,AAA,AA}X

\end{document}

在此处输入图片描述

注意:如果你运行的是 2020-10-01 版本之前的 LaTeX,你需要

\usepackage{xparse}

相关内容