xparse 创建无限循环

xparse 创建无限循环

此 MWE 在我的计算机上创建了一个无限循环。有人能向我解释一下原因吗?

\documentclass{article}

\usepackage{booktabs,xparse}
    \NewDocumentCommand\hlineX{ m O{0pt} O{#2} }{%
        \specialrule{#1}{#2}{#3}%
    }%

\begin{document}
    \begin{tabular}{|l|l|l|}
        \hline
        1    & 2    & 3 \\
        \hlineX{1pt}
        4    & 5    & 6 \\
        \hline
    \end{tabular}
\end{document}

在我创建的主要文档中,我遇到了不同的错误: "Misplaced \noalign. [ E]" "Missing } inserted. [ E]"等等。它非常像 MWE,但加载了更多包。

当我使用\specialrule没有xparse它的命令时,它工作得很好。

答案1

似乎应该\hlineX是可扩展的,因为一个简化的例子也会导致同样的问题。

\documentclass{article}

\usepackage{booktabs,xparse}
\protected\def\xline{\specialrule{1pt}{0pt}{0pt}}

\begin{document}
    \begin{tabular}{|l|l|l|}
        \hline
        1    & 2    & 3 \\
        \xline
        4    & 5    & 6 \\
        \hline
    \end{tabular}
\end{document}

的可扩展变体\NewDocumentCommand\NewExpandableDocumentCommand,并且由于它定义了可扩展的新命令,因此参数规范不应以可选参数结尾。因此,我们有以下工作示例,其语法经过\hlinex修改:

\documentclass{article}

\usepackage{booktabs,xparse}
    \NewExpandableDocumentCommand\hlineX{ O{0pt} O{#1} m }{%
        \specialrule{#3}{#1}{#3}%
    }

\begin{document}
    \begin{tabular}{|l|l|l|}
        \hline
        1    & 2    & 3 \\
        \hlineX[1pt][2pt]{1pt}
        4    & 5    & 6 \\
        \hline
    \end{tabular}
\end{document}

答案2

muzimuzhi Z 的回答显示了您应该做什么来避免错误(您可能应该接受这个错误),但您的实际问题是询问为什么它会循环而不是如何避免错误。

循环与 xparse 其实没什么关系,除了寻找一个可选参数,之前是不允许的\specialrule(或者\hrule或者\multicolumn或者\rowcolor类似的特殊表格单元格命令)如果看到任何不可扩展的材料,单元格模板就会启动,而且插入规则的不对齐材料就太晚了。

循环的一个简单示例是

\documentclass{article}

\usepackage{booktabs}


\begin{document}


\tracingall
    \begin{tabular}{|l|l|l|}
        \hline
        1    & 2    & 3 \\
        \relax\specialrule{0pt}{0pt}{1pt}
        4    & 5    & 6 \\
        \hline
    \end{tabular}
\end{document}

正如您的示例所示,这会停止并显示几个本质上是虚假的错误消息,但如果您滚动浏览它们,最终会遇到一个紧密循环并且必须终止程序,\tracingall将显示:

.
.
.
\par ->
{\hrule}

\par ->
{\hrule}

\par ->
{\hrule}
.
.
.

这表明你实际上已经遇到了这个众所周知的循环条件:

\documentclass{article}

\begin{document}

{\let\par\relax x\hrule}

\end{document}

这使得 TeX 永远运行而不会出现任何错误。

\hrule,在垂直模式下,只允许在段落之间插入一条横跨页面的水平线。如果在水平模式下遇到此标记,TeX 不会引发错误,它会在标记\par之前插入标记以结束当前段落,\hrule然后正常进行。

需要注意的是,与水平模式下垂直框结束的类似情况不同,TeX 不会执行原始的段落结束代码,而是直接将标记插入\par输入流。

因此,如果像这里一样(并且由于 latex 表格中的技术原因)\par在本地定义为不执行任何操作,则\hrule触发插入,\par其不执行任何操作,然后\hrule再次看到,插入\par....

相关内容