用于定义宏并按顺序调用它们的宏(Tex)

用于定义宏并按顺序调用它们的宏(Tex)

简要地,

纯特克斯

% THE FIRST ARGUMENT SHOULDN'T NEED TO RECEIVE \ AS FIRST CHARACTER
\global\def\futuredef#1#2{\global\def\#1{#2}#2}
\futuredef{love}{doesn't exist}
\love % Gives a error!

% THE FIRST ARGUMENT NEED TO RECEIVE \ AS FIRST CHARACTER
\global\def\futuredef#1#2{\global\def#1{#2}#2}
\futuredef\love{exists}
\love % Works fine

如何使“futuredef”的第一个版本可操作?如果我想使用最近创建的宏,如何在同一个宏(刚刚定义它)中调用它?例如

\global\def\futuredef#1#2{\global\def#1{#2}\csname#1\endcsname}
%but doesn't work!!! generates prematurely a error when running it (OUTPUT: Missing $ ) -- WHAT HELL!?!?!
\futuredef\love{exists}
\love % and fails again!

答案1

你说:

如何使“futuredef”的第一个版本可操作?如果我想使用最近创建的宏,如何在同一个宏(刚刚定义它)中调用它?例如

\global\def\futuredef#1#2{\global\def#1{#2}\csname#1\endcsname}
%but doesn't work!!! generates prematurely a error when running it (OUTPUT: Missing $ ) -- WHAT HELL!?!?!
\futuredef\love{exists}
\love % and fails again!

如果我理解正确的话,\futuredef当只提供表示宏名称的标记序列(而不是宏标记本身)时,应该定义并调用宏。

您快完成了!

您的代码中已经有了\csname#1\endcsname根据名称生成控制序列标记的功能。
您还需要\csname..\endcsname在执行之前让 TeX 应用\def— 否则\def不会应用于待定义的控制序列标记,而是应用于表示待定义的控制序列标记名称的标记序列的第一个标记。而这将行不通,因为\defTeX 需要控制序列标记,而不是其名称。
当然,\futuredef然后将作为其第一个参数处理控制序列标记的名称,而不是控制序列标记本身:

\global\def\futuredef#1#2{\global\expandafter\def\csname#1\endcsname{#2}\csname#1\endcsname}
%Let's both globally define and call \love:
\futuredef{love}{\message{love exists}}%
%Let's call \love again:
\love % This does not fail. ;-)
\bye

(生成 .pdf 文件是我有时会吝啬的事情。;-) 所以我决定将\love其定义为一个生成的宏,\message因为这样就不会创建 .pdf 文件,而且您在控制台上无论如何都会看到有事情发生。)

控制台输出:

This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) (preloaded format=pdftex)
 \write18 enabled.
entering extended mode
(./test.tex love exists love exists )
No pages of output.
Transcript written on test.log.

但这种方法不允许您提供⟨参数文本⟩使用 提供的定义\futuredef。因此,使用此方法,您只能用于\futuredef定义不处理参数/参数分隔符的宏。



定义并立即调用宏对我来说也很有意义,尤其是在新定义的宏要处理\futuredef宏后面的参数的情况下。为了考虑参数文本,我建议#{使用语法:

2020年11月21日补充说明:

在评论中,您要求澄清#{-notation 的含义:

您的变体\futuredef并非设计用于定义(并在定义后立即调用)处理参数/参数的宏#1,,#2...
您想要的语法是:

\futuredef{⟨macro name⟩}{⟨definition text⟩}

我已经扩展它,以便你也可以这样做:

\futuredef{⟨macro name}⟩#1#2..#9{⟨definition text⟩}
\futuredef{⟨macro name⟩}⟨parameter text⟩{⟨definition text⟩}

对于这个,\futuredef除了它的第一个参数(它包含 ⟨宏名⟩)第二个参数,{⟨定义文本⟩并持有构成⟨参数文本⟩

在 TeX 中,有一种特殊情况,即宏的最后一个参数(例如,\futuredef下面宏的第二个参数)由左花括号分隔,如果你#在后面写了一个⟨参数文本⟩该宏的⟨定义⟩. 由于⟨定义文本⟩紧接着#,这就叫#{语法。

(与其他参数分隔符不同,在收集宏的参数时不会删除这样的开括号,而是将其留在原处并出现在该宏的替换文本的正后方。)

\long\def\futuredef#1#2#{%
  % #1 - tokens yielding character tokens forming the name of the to-be-defined control-sequence token
  % #2 - parameter text, delimited by { of the following definition-text
  \expandafter\innerfuturedef\expandafter{\csname#1\endcsname}{#2}%
}%
\long\def\innerfuturedef#1#2#3{%
  % #1 - to-be-defined control-sequence token
  % #2 - parameter text
  % #3 - definition text
  \def#1#2{#3}% <- let's define #1
  #1% <- let's call #1
}%
% Now introduce a local scope:
\begingroup
% Now let's both globally define \macro to process 3 arguments and call \macro for processing the 3 arguments {A}{B}{C}:
\global\long\futuredef{macro}#1#2#3{\message{Arg1: #1, Arg2: #2, Arg3: #3}}{A}{B}{C}%
% Now close the local scope:
\endgroup
% Let TeX display on the console how `\macro` is defined:
\show\macro
% Now let's both define and call \macroB which does not take arguments:
\futuredef{macroB}{\message{A nice message.}}%
% Let TeX display on the console how `\macroB` is defined:
\show\macroB
\bye

控制台输出为:

This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) (preloaded format=pdftex)
 \write18 enabled.
entering extended mode
(./test.tex Arg1: A, Arg2: B, Arg3: C
> \macro=\long macro:
#1#2#3->\message {Arg1: #1, Arg2: #2, Arg3: #3}.
l.20 \show\macro
                
? 
A nice message.
> \macroB=macro:
->\message {A nice message.}.
l.24 \show\macroB
                 
? 
 )
No pages of output.
Transcript written on test.log.

如果不需要像\long\global\protected这样的前缀\outer,那么您可以直接使用\afterassignment

\long\def\futuredef#1{%
  % #1 - tokens yielding character tokens forming the name of the to-be-defined control-sequence token
  \expandafter\afterassignment\csname#1\endcsname 
  \expandafter\def\csname#1\endcsname 
}%
% Now let's both within the current scope define \macro to process 3 arguments and call \macro for processing the 3 arguments {A}{B}{C}:
\futuredef{macro}#1#2#3{\message{Arg1: #1, Arg2: #2, Arg3: #3}}{A}{B}{C}%
% Let TeX display on the console how `\macro` is defined:
\show\macro
\bye

相关内容