我经常使用缩写 \nin 来定义
\newcommand{\nin}{\not\in}
但是,当我开始使用 xelatex 和 unicode-math 执行此操作时,它会导致 xelatex 停滞。特别是以下文档似乎使 xelatex 陷入无限循环
\documentclass{amsart}
\usepackage{unicode-math}
\newcommand{\nin}{\not\in}
\begin{document}
\( a \nin b \)
\end{document}
坦率地说,我很困惑,因为我的命令是在所有包加载之后定义的(即使我在开始文档之后定义命令仍然会失败)并且没有现有命令与它冲突,那么发生了什么?
有什么方法可以让这个宏工作吗(理想情况下以在 xelatex+unicode-math 和 pdflatex 中都有效的方式)
需要明确的是定义\nin 加上 \not\in 的使用会造成麻烦,就像我替换一样。
\( a \nin b \)
和
\( a \not\in b \)
它仍然停滞,但如果我将其替换为
\( a \in b \)
它执行得很好。
根据 egreg 的评论,我可以将 \nin 定义为 \notin,并且一切都可以正常编译。不过,我仍然想知道这里发生了什么,这样我就不会再遇到同样的问题。
答案1
\not
定义如下unicode-math
:
\cs_new:Npn \__um_newnot:N #1
{
\tl_set:Nx \l_not_token_name_tl { \token_to_str:N #1 }
\exp_args:Nx \tl_if_empty:nF { \tl_tail:V \l_not_token_name_tl }
{
\tl_set:Nx \l_not_token_name_tl { \tl_tail:V \l_not_token_name_tl }
}
\cs_if_exist:cTF { n \l_not_token_name_tl }
{
\use:c { n \l_not_token_name_tl }
}
{
\cs_if_exist:cTF { not \l_not_token_name_tl }
{
\use:c { not \l_not_token_name_tl }
}
{
\__um_oldnot: #1
}
}
}
这\__um_oldnot:
是遗留的\not
;在文档开始时,\not
设置为等于\__um_newnot:N
。
本质上,当您执行 时\not\foo
,宏会检查 是否\nfoo
已定义(多个否定符号以此方式命名)。否则,它会检查\notfoo
,如果失败,则使用否定斜杠。
你看到问题了吗?如果\nin
按照你的方式定义,它就会被执行,从而重新启动循环,因为它确实\not\in
……无限循环。
请注意,\not\in
自 TeX(及其标准字体)诞生的第一天起,它就是错误的,而应该是\notin
。
解决方案
\newcommand{\nin}{\notin}
评论
的基本思想unicode-math
是帮助用户获得正确的符号。您的案例表明用户忽略了使用的建议,\notin
而不是:您能发现使用和 Computer Modern\notin
时的区别吗?pdflatex
类似地,经常会发现\not\mid
而不是\nmid
。
更重要的是,如果 Unicode 字符集中存在否定符号,则应该可以独立于用户输入使用。因此\not\mid
應該内部转换为\nmid
,类似地\not\in
转换为\notin
(其中unicode-math
表示单个字符,而不是像传统字体那样两个字形的叠加)。如果我们查看unicode-math-table.tex
,我们会发现
\nexists
\notin
\nni
\nmid
\nparallel
\nsim
以及其他几个。可能还应该有\nin
,但传统上称之为\notin
。
请注意,如果您定义\nfoo
为\not\foo
,那么您会遇到与相同的问题\in
。