无法使 \xappto 工作

无法使 \xappto 工作

我正在尝试学习如何使用\xappto,并且一直在使用这个示例。为什么它不起作用?当我after row=\noexpand\midrule直接传递\codeforpgf{}时,它工作正常,但当我使用 时,出现了问题\xappto

\documentclass{article}
\RequirePackage{etoolbox}
\RequirePackage{pgfplotstable}
\RequirePackage{pgfplots}
\usepackage{booktabs}

\begin{filecontents*}{test.csv}
    ColA, ColB, ColC
    0.17, 0.91, 0.67
    0.15, 0.17, 0.92
    0.48, 0.1, 0.28
\end{filecontents*}

\def\buildTable#1{%
    \def\temp{after row=\noexpand\midrule}%
    \def\codeforpgf{}%
    \expandafter\xappto\expandafter\codeforpgf\expandafter{\temp}%
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \xdef\theTable{\noexpand\pgfplotstabletypeset[\codeforpgf]}%
    \theTable{\rawdata}%    
}%

\begin{document}
\begin{table}
    \buildTable
    {%CSV file
        test.csv%
    }
\end{table}
\end{document}

答案1

egreg 和 Ulrike Fisher 是对的。在我看来,这是一个不必要的复杂且危险的定义。\buildTable可以写得更简单:

\def\buildTable#1{%
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \pgfplotstabletypeset[after row=\midrule]{\rawdata}%
}%

但是您想了解\xappto,因此这里解释了出了什么问题:

首先,你不需要所有的\expandafters,因为\xappto会为你扩展\temp。但这不是什么大问题,因为有了\expandafters 基本上就像写作\xappto\codeforpgf{after row=\noexpand\midrule}一样。主要问题是 中的第二次扩展\xdef

\noexpand扩展时,它会将下一个标记(在您的情况下为\midrule)复制回输入流而不进行扩展。此后,\noexpand消失,它完成了工作。此扩展在 中完成\xappto。因此,不要写成

\def\temp{after row=\noexpand\midrule}%
\def\codeforpgf{}%
\xappto\codeforpgf{\temp}%

你可以写

\def\codeforpgf{after row=\midrule}%

会产生同样的结果和同样的错误后者因为 now\xdef会尝试扩展\midrule到表之外,这不是一个好主意。

\def\codeforpgf{after row=\noexpand\midrule}%

将会\xdef按预期工作。为了使\midrule通过两个扩展的扩展不展开,必须编写

\def\temp{after row=\noexpand\noexpand\noexpand\midrule}%

在您的宏中,您也可以使用\appto而不是 来\xappto使其发挥作用。

在下面的代码中我插入了几个\shows。\show\somemacro将在日志文件中显示 的定义\somemacro。例如, \buildTableC将写入

> \temp=macro:
->after row=\noexpand \noexpand \noexpand \midrule .

到日志中。通过这个你可以看到\noexpands 是如何消失的。搜索许多X,我用 写入日志\typeout

代码:

\documentclass{article}
\RequirePackage{etoolbox}
\RequirePackage{pgfplotstable}
\RequirePackage{pgfplots}
\usepackage{booktabs}

\begin{filecontents*}{test.csv}
    ColA, ColB, ColC
    0.17, 0.91, 0.67
    0.15, 0.17, 0.92
    0.48, 0.1, 0.28
\end{filecontents*}

% better and easier definition of \buildTable
\def\buildTableA#1{%
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \pgfplotstabletypeset[after row=\midrule]{\rawdata}%
}%

% unnecessarily complicated and dangerous definition, using \appto instead of \xappto
\def\buildTableB#1{%
    \def\temp{after row=\noexpand\midrule}%
    \def\codeforpgf{}%
    \typeout{XXXXXXXXXXXXXXXXXXXX \string\buildTableB}%
    \show\temp
    \show\codeforpgf
    \appto\codeforpgf{\temp}%
    \show\codeforpgf
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \xdef\theTable{\noexpand\pgfplotstabletypeset[\codeforpgf]}%
    \show\theTable
    \theTable{\rawdata}%    
}%

% unnecessarily complicated and dangerous definition
\def\buildTableC#1{%
    \def\temp{after row=\noexpand\noexpand\noexpand\midrule}%
    \def\codeforpgf{}%
    \typeout{XXXXXXXXXXXXXXXXXXXX \string\buildTableC}%
    \show\temp
    \show\codeforpgf
    \xappto\codeforpgf{\temp}%
    \show\codeforpgf
    \pgfplotstableread[col sep = comma]{#1}\rawdata%
    \xdef\theTable{\noexpand\pgfplotstabletypeset[\codeforpgf]}%
    \show\theTable
    \theTable{\rawdata}%    
}%

\begin{document}
\begin{table}
    \buildTableA{test.csv}

    \buildTableB{test.csv}

    \buildTableC{test.csv}
\end{table}
\end{document}

相关内容