我想在 LaTeX3 中的组中定义一个宏,以便它在组之后保持定义,但不使用全局变量。现在我这样做:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentEnvironment{test}{}{}{
\str_clear_new:N \mytest
\str_put_right:Nx \mytest {I ~ like ~}
\str_gset_eq:NN \dummyvar \mytest
\group_insert_after:N \str_set_eq:NN
\group_insert_after:N \mytest
\group_insert_after:N \dummyvar
}
\ExplSyntaxOff
\begin{document}
\def\mytest{chocolate.}
{
\begin{test}
I’d like mytest to be defined at the end of the group without using global variables.
\end{test}
\mytest
}
\mytest
\end{document}
它可以工作,但是看起来真的很脏,比如我需要引入一个全局虚拟变量等等...我尝试这样做:
\group_insert_after:N \str_set_eq:NN
\group_insert_after:N \mytest
\expandafter \group_insert_after:N \mytest
但有趣的是,这个字符串现在是倒着写的!!我也试图生成一个变体,\group_insert_after:V
但这是被禁止的。
答案1
我理解,\dummyvar
如果你想在组后保留多个宏的含义,那么这种方法行不通。但你可以设置一个从给定控制序列的名称派生的控制序列:
\def\keepaftergroup#1{%
\global \expandafter\let \csname x:\string#1\endcsname =#1
\aftergroup\let
\aftergroup#1%
\expandafter\aftergroup \csname x:\string#1\endcsname
}
\def\mytest{nazdar}
{
\def\mytest{Hello}
\def\mysecond{Hi}
\keepaftergroup\mytest
\keepaftergroup\mysecond
Text in group.%
}
After group: \mytest, \mysecond
答案2
我们目前没有“脱离任意组级别”功能,主要是因为这是一个不寻常的要求。另一方面,如果你想在你控制的组之外设置变量,这很简单
\group_begin:
% Stuff happens
\str_set:Nn \l__mypkg_str { ... }
\exp_args:NNNV \group_end:
\str_set:Nn \l__mypkg_str \l__mypkg_str
等等。
答案3
下面定义了一种使用单个辅助全局令牌将物品走私到上一级的机制。
它不适用于toks
寄存器。我希望我没有搞砸实现的其他方面。
\documentclass{article}
\ExplSyntaxOn
\tl_new:N \g__tobiasbora_smuggler_tl
\cs_new:Npn \tobiasbora_smuggle:n #1
{
\tl_gset:Nx \g__tobiasbora_smuggler_tl
{
\tl_map_function:nN {#1} \__tobiasbora_smuggle:N
\exp_not:n { \tl_gset:Nn \g__tobiasbora_smuggler_tl }
{ \exp_not:o \g__tobiasbora_smuggler_tl }
}
\group_insert_after:N \g__tobiasbora_smuggler_tl
}
\cs_new:Npn \__tobiasbora_smuggle:N #1
{
\token_if_macro:NTF #1
{
\exp_not:n { \cs_set:Npx #1 }
{ \exp_not:N \exp_not:n { \exp_not:o #1 } }
}
{
\token_if_chardef:NTF #1
{ \exp_not:n { \chardef #1 } = \exp_not:V #1 \scan_stop: }
{
\token_if_mathchardef:NTF #1
{ \exp_not:n { \mathchardef #1 } = \exp_not:V #1 \scan_stop: }
{
% assume it's a register type and the following is fine
#1 = \exp_not:V #1 \scan_stop:
}
}
}
}
\NewDocumentEnvironment{test}{}{}{
\str_set:Nn \mytest { like~ }
\tobiasbora_smuggle:n { \mytest \mycount }
}
\ExplSyntaxOff
\newcount\mycount
\mycount=0
\begin{document}
\def\mytest{chocolate.}
{
\begin{test}
I’d like mytest to be defined at the end of the group without using global variables.
\mycount=1
\end{test}%
\uppercase\expandafter{\romannumeral\mycount} % this prints "I"
\mytest
}%
\mytest
\romannumeral\mycount % this prints nothing as it's 0 again
\end{document}