将宏从 tex 核心中的组中走私出来会导致未定义的控制序列

将宏从 tex 核心中的组中走私出来会导致未定义的控制序列

我试图直接使用以下类似代码重新应用组中所做的更改按照这里的方法

\def\smuggle#1\endgroup{%
  \expandafter\endgroup\expandafter\edef\expandafter#1\expandafter{#1}%
}
\begingroup
  \def\variable{12}
  \edef\variable{\variable34}
  \edef\variable{\variable56}
  \def\var {A}%
  \edef\changes{%
    \noexpand\def\noexpand\variable{\variable}%
    \noexpand\def\noexpand\var{\var}%
  }%
  \smuggle\changes
\endgroup
\message{\meaning\changes}
\changes
\message{value of \variables , \vars }
\end

但是,编译时出现错误

! Undefined control sequence.
\changes ->\def \variable 
                          {123456}\def \var {A}
\smuggle ... \edef \expandafter #1\expandafter {#1
                                                  }
l.14 \endgroup

我不知道该如何解释。 或 是或\changes之一未定义吗? 还是扩展有问题? 据我所知,这应该扩展为\variable\var

\endgroup
\edef\changes{%
    \def\variable{123456}%
    \def\var{A}%
}%
\message{ [...]

但事实似乎并非如此。您能给我一些提示,告诉我哪里没有按预期运行吗?

答案1

\smuggle命令依赖于被走私的命令,只需一步即可完全展开

如果你\def\foo{zzz}

\smuggle\foo\endgroup

结果是

\endgroup\def\foo{zzz}

因此该值在组外被保留(或重新设置)。

\changes定义为

\def \variable {123456}\def \var {A}

不可扩展

链式\expandafter设计\smuggle用于将令牌扩展一步,并旨在与之一起使用,\def但您却遇到了\edef导致\variable您显示的错误而扩展的情况。

\def将获得:

\def\smuggle#1\endgroup{%
  \expandafter\endgroup\expandafter\def\expandafter#1\expandafter{#1}%
                                    %%%
}
macro:->\def \variable {123456}\def \var {A}

就像\changes复制到组外一样,但在下面的操作中会出现错误

\message{\variables 的值,\vars }

我认为这是拼写错误\variable

因此无错误日志

This is pdfTeX, Version 3.141592653-2.6-1.40.23 (TeX Live 2022/dev) (preloaded format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./bb320.tex macro:->\def \variable {123456}\def \var {A} value of 123456, A )
No pages of output.

\def\smuggle#1\endgroup{%
  \expandafter\endgroup\expandafter\def\expandafter#1\expandafter{#1}%
}
\begingroup
  \def\variable{12}
  \edef\variable{\variable34}
  \edef\variable{\variable56}
  \def\var {A}%
  \edef\changes{%
    \noexpand\def\noexpand\variable{\variable}%
    \noexpand\def\noexpand\var{\var}%
  }%
  \smuggle\changes
\endgroup
\message{\meaning\changes}
\changes
\message{value of \variable , \var }
\end

答案2

David 已经解释错误来源。这里有一个不同的方法

\newlinechar=`\^^J % for readable messages

\def\smuggle#1\endgroup{%
  \toks0=\expandafter{#1}%
  \edef\x{\endgroup\def\noexpand#1{\the\toks0}}\x
}
\begingroup
  \def\variable{12}
  \edef\variable{\variable34}
  \edef\variable{\variable56}
  \def\var {A}%
  \edef\changes{%
    \noexpand\def\noexpand\variable{\variable}%
    \noexpand\def\noexpand\var{\var}%
  }%
  \smuggle\changes
\endgroup

\message{^^J***\noexpand\changes is \meaning\changes***^^J}

\changes

\message{^^J***value of \noexpand\variable and \noexpand\var is \variable, \var***^^J}

\end

代码利用了这样一个事实,即\the\toks0令牌列表已交付但未进一步扩展\edef

This is TeX, Version 3.141592653 (TeX Live 2021) (preloaded format=tex)
(./smuggle.tex

***\changes is macro:->\def \variable {123456}\def \var {A}***

***value of \variable and \var is 123456, A***
 )
No pages of output.
Transcript written on smuggle.log.

相关内容