\csdef 的古怪行为

\csdef 的古怪行为

我用来\csdef{}定义给定开/闭括号的含义:

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |}
\csdef{Bracket Meaning \CsToStr{\rvert}}{Right |}
\csdef{Bracket Meaning \CsToStr{(}}{open (}
\csdef{Bracket Meaning \CsToStr{)}}{close )}

前两个和最后一个似乎可以正常工作,但第三个有问题。当我尝试通过#1~\csuse{Bracket Meaning \CsToStr{#1}}(其中#1是四个给定括号之一\lvert\rvert和)访问它们时()输出为:

在此处输入图片描述

我原本期望用红色突出显示的是( open (

那么,这里发生了什么,我应该如何重组它以获得所需的括号结果(

代码:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{xcolor}

%% Following package not needed with newer binaries
\usepackage{expl3}%    \cs_to_str:N

\ExplSyntaxOn
    %% https://tex.stackexchange.com/a/100543/4301
    \newcommand{\CsToStr}[1]{\cs_to_str:N #1}%
\ExplSyntaxOff

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |}
\csdef{Bracket Meaning \CsToStr{\rvert}}{Right |}
\csdef{Bracket Meaning \CsToStr{(}}{open (}% FAILS !!
\csdef{Bracket Meaning \CsToStr{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{%
    #1~
    \ifcsdef{Bracket Meaning \CsToStr{#1}}{%
        \csuse{Bracket Meaning \CsToStr{#1}}%
     }{\text{No Meaning Defined}}%
}%

\begin{document}
$\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

{\color{red}%
    $\ShowBracketMeaning{(}$% <---- ????? This should show "open ("
}

$\ShowBracketMeaning{)}$
\end{document}

答案1

如果你试试

\edef\test{\CsToStr{(}}
\show\test

你会发现答案是

> \test=macro:
->.

\cs_to_str:N功能应该仅有的应用于控制序列;否则其结果是不可预测的(好吧,它是可预测的,但无论如何似乎不是你想要得到的)。

由于和都\CsToStr{(}返回\CsToStr{)}空,因此涉及它们的第二个定义将覆盖第一个。

解决方案:如果你真的想要那个,不要使用\CsToStr

\csdef{Bracket Meaning \CsToStr{\lvert}}{Left |}
\csdef{Bracket Meaning \CsToStr{\rvert}}{Right |}
\csdef{Bracket Meaning (}{open (}
\csdef{Bracket Meaning )}{close )}

另一方面,当您形成控制序列时,不需要删除反斜杠,只要反斜杠是“其他”即可。

\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\TokenToStr}{m}{\token_to_str:N #1}%
\NewExpandableDocumentCommand{\csdefinedTF}{mmm}
 {
  \cs_if_exist:cTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

\ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{\lvert}}{Left |}
\ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{\rvert}}{Right |}
\ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{(}}{open (}
\ExpandArgs{c}\newcommand{Bracket Meaning \TokenToStr{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{%
    #1~
    \csdefinedTF{Bracket Meaning \TokenToStr{#1}}{%
        \UseName{Bracket Meaning \TokenToStr{#1}}%
     }{\text{No Meaning Defined}}%
}

\begin{document}

$\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

$\ShowBracketMeaning{(}$

$\ShowBracketMeaning{)}$

\end{document}

在此处输入图片描述

答案2

在 egreg 发布详细的解决方案之前,我发现使用\detokenize{}而不是依赖\CsToStr{}可以产生预期的结果。

我发布此信息是为了查看这种方法是否存在我不知道的问题。

代码:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{amsmath}
\usepackage{xcolor}

\csdef{Bracket Meaning \detokenize{\lvert}}{Left |}
\csdef{Bracket Meaning \detokenize{\rvert}}{Right |}
\csdef{Bracket Meaning \detokenize{(}}{open (}
\csdef{Bracket Meaning \detokenize{)}}{close )}

\newcommand{\ShowBracketMeaning}[1]{%
    #1~
    \ifcsdef{Bracket Meaning \detokenize{#1}}{%
        \csuse{Bracket Meaning \detokenize{#1}}%
     }{\text{No Meaning Defined}}%
}%

\begin{document}
$\ShowBracketMeaning{\lvert}$

$\ShowBracketMeaning{\rvert}$

$\ShowBracketMeaning{(}$

$\ShowBracketMeaning{)}$
\end{document}

相关内容