检查命令可扩展性的宏

检查命令可扩展性的宏

我想创造检查表达式是否完全可展开的命令,如果不能则崩溃(最好打印一条错误消息)。我想这样做没有考虑特定的 TeX 引擎。我认为这与这个问题有关检查宏是否完全可扩展,但提供的答案需要LuaTeX。


测试代码

测试代码如下:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xstring}

\NewDocumentCommand{\checkexpandability}{m}{
    % CODE HERE
}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}

\begin{document}
\checkexpandability{\expandable{test}} % Should be OK
\checkexpandability{\notexpandable{test}} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}} % Should CRASH
\end{document}

如果太复杂

如果不可行,那么我可以修改命令签名以包含命令应该扩展为的参数:

\begin{document}
\checkexpandability{\expandable{test}}{test} % Should be OK
\checkexpandability{\notexpandable{test}}{test} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}}{true} % Should CRASH
\end{document}

可扩展性评价

由于完全可扩展的定义并不像人们想象的那么清晰(见下面的评论),这个问题的背景是我只是想创建一些可以帮助我调试一些代码的东西。我可以将问题限制在这个特定的行为上:宏是否可以在上下文宏中工作,例如命令\color

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\color{\expandable{blue}} % OK
\color{\notexpandable{red}} % CRASHES
X
\end{document}

基本上,该\color命令可以完成我所寻找的工作,只是我想调用它\checkexpandability,使其更通用一些,并打印一条很好的错误消息。

答案1

我认为基本的误解是

基本上,这个\color命令可以完成我所寻找的工作,

\color命令不会检查请求的类型,它只是期望扩展后参数是已定义的颜色名称。如果扩展失败,您将收到低级错误,或者如果它扩展为未定义的颜色,您将收到特定的错误消息,但处理的任何部分都不是通用的,也不适用于除需要颜色的命令之外的命令。

可以实现的一个版本是具有预期扩展的版本,因为它只是询问扩展后两个参数是否相等。 L3 编程层有几种变体,或者您可以使用包ifthen

\ifthenelse{\equal{\expandable{test}}{test}}{yes}{no}

如果参数扩展为相同内容,则返回“是”,否则返回“否”,如果参数在扩展上下文中不安全(这通常就是“不可扩展”的含义),则给出低级错误

答案2

为了调试你的代码,我只需使用\typeout

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\typeout{\expandable{blue}} % OK, print "blue"
\typeout{\notexpandable{red}} % CRASHES
X
\end{document}

关键是它将\typeout完全展开其参数,然后在终端上打印完全展开的结果 --- 因此您只需查看终端即可。

对于第一种情况,它会打印blue,所以一切正常。对于第二种情况,它会崩溃。


当然,上述方法存在两个问题。

  • 即使\expandable{blue} 完全可扩展(无论其含义如何),\color在将结果解释为颜色之前,可能不能保证充分展开其参数(我猜海仑律法但实际上这是为了避免破坏“现有的包裹”。)

    因此,如果你想要更加确定,最好提前使用例如进行扩展\ExpandArgs

  • 类别代码的信息以及代码中隐藏的任何特殊字符(例如空格与制表符)都会丢失。

    在实践中这并不重要,但有时确实如此。(例如,当您尝试调试某个试图逐字捕获环境主体的包时)

    如果是这样,可以考虑尝试一下我的包裹.(目前代码很乱,但是运行良好,而且有源代码更糟糕的软件包)

相关内容