NewDocumentCommand 中的 Def 失败了?

NewDocumentCommand 中的 Def 失败了?

我想将参数重命名#1为类似的名字,\ies@firstStar这样编程时就不会出错,在更改函数参数时也无需重命名变量。但是执行类似操作\def\ies@firstStar{#1}会失败,您知道哪里出了问题吗?

\documentclass{article}
\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\myTest}{s}{
  \bgroup% make definitions local
  \def\ies@firstStar{#1}%
  \IfBooleanTF{\ies@firstStar}{%
    One star
  }{%
    No star
  }
  \egroup
}

\makeatother

\begin{document}
\myTest
\end{document}

答案1

使用\let代替来\def避免使用\expandafters。在\def替换文本\ies@firstStar或。在\BooleanFalse\BooleanTrue情况下\let\ies@firstStar实际上等价于\BooleanFalse\BooleanTrue

正如 Gaussler 所指出的,\let只能分配一个标记。因此,这种方法是有效的,因为s参数永远不会超过一个标记。

\documentclass{article}
\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\myTest}{s}{%
  \begingroup% make definitions local
  \let\ies@firstStar=#1%
  \IfBooleanTF{\ies@firstStar}{%
    One star%
  }{%
    No star%
  }%
  \endgroup
}

\makeatother

\begin{document}
\myTest
\myTest*
\end{document}

在此处输入图片描述

答案2

在内部,我不确定具体是如何\IfBooleanTF工作的,但下面的方法解决了这个问题。然而,至少在这个简单的例子里,我看不出这如何使代码更具可读性。

\documentclass{article}
\usepackage{xparse}

\makeatletter
\NewDocumentCommand{\myTest}{s}{
  \begingroup% better to use this than \bgroup...\egroup
  \def\ies@firstStar{#1}%
  \expandafter\IfBooleanTF\expandafter{\ies@firstStar}{%
    One star
  }{%
    No star
  }
  \endgroup
}

\makeatother

\begin{document}
\myTest
\myTest*
\end{document}

在此处输入图片描述

答案3

很难理解这种间接性的必要性。

无论如何,当前的参数类型的实现s是,如果是第一个参数,则在没有 的情况下分配s给 的值,如果有。#1*\BooleanFalse\BooleanTrue*

然后当前的的实现\IfBooleanTF{#1}{True}{False}根据是否#1\BooleanTrue​​或来选择真或假分支\BooleanFalse。接下来你可能想知道现在 \BooleanTrue\BooleanFalse\chardef令牌,所以它们不可扩展。

但用户/程序员应该不是依赖这一点。在未来的版本中,这可能会改变;不太可能发生,但是,嘿!谁知道呢?

此外,我看不出 比 有什么优势\IfBooleanTF{\ies@FirstStar}\IfBooleanTF{#1}相反,我看到了几个缺点,例如,您需要分组以避免时间扩展或宏破坏。

为什么你的代码不起作用\def?因为与或\ies@FirstStar不同:它是一个扩展到它们任何一个的宏(和用于检查,而不是不起作用,因此不执行扩展)。如果你按照建议使用而不是代码\BooleanTrue\BooleanFalseexpl3\ifx\if\let\def似乎可以工作,但可能会在 的未来版本中停止工作expl3。相反,\IfBooleanTF{#1}保证永远有效。

相关内容