如何在 expl3 中的宏中使用局部变量

如何在 expl3 中的宏中使用局部变量

我延长了egregs 回答通过定义一个宏,在一行中创建并初始化一个 fp 值。然后将变量放入一个序列并打印该序列:

\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\setlength{\parindent}{0cm}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand{\newfpvar}{m}{\fp_new:N #1}
\NewDocumentCommand{\setfpvar}{mm}{\fp_set:Nn #1 { #2 }}
\NewDocumentCommand{\getfpvar}{m}{\fp_use:N #1}

%my new macro
\NewDocumentCommand{\define_fp_var}{mm}{
  \newfpvar{#1}
  \setfpvar{#1}{#2}
}

%define 3 variables
\define_fp_var{\One}{1}
\define_fp_var{\Two}{2}
\define_fp_var{\Three}{3}

%put them into sequence
\seq_new:N \fp_seq
\seq_put_right:Nn \fp_seq {\One}
\seq_put_right:Nn \fp_seq {\Two}
\seq_put_right:Nn \fp_seq {\Three}

%print sequence
\seq_map_inline:Nn \fp_seq
{
  \getfpvar{#1}\\
}

\ExplSyntaxOff
\end{document}

印刷:

在此处输入图片描述

我尝试创建一个宏,当我可以定义一个值并将其推送到一行中的序列中时,但它不起作用:

\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\setlength{\parindent}{0cm}
\begin{document}
\ExplSyntaxOn
\NewDocumentCommand{\newfpvar}{m}{\fp_new:N #1}
\NewDocumentCommand{\setfpvar}{mm}{\fp_set:Nn #1 { #2 }}
\NewDocumentCommand{\getfpvar}{m}{\fp_use:N #1}

%my new macro
\NewDocumentCommand{\define_fp_var}{mm}{
  \newfpvar{#1}
  \setfpvar{#1}{#2}
}

%this doesn't work
%#1 - sequence name
%#2 - value
\NewDocumentCommand{\seq_put_fp_var_right}{mm}{
  \group_begin:
  %variable redefined
  \define_fp_var{\temp}{#2}
  \seq_put_right:Nx #1 \temp
  \group_end:
}

\seq_new:N \fp_seq
\seq_put_fp_var_right \fp_seq {1}
\seq_put_fp_var_right \fp_seq {2}
\seq_put_fp_var_right \fp_seq {3}

\seq_map_inline:Nn \fp_seq
{
  \getfpvar{#1}\\
}

\ExplSyntaxOff
\end{document}

打印错误:

Control sequence \temp already defined.

l.28 \seq_put_fp_var_right \fp_seq {2}

如何在本地定义一个变量并将其存储在序列中?

我读过这个:LaTeX3:如何在本地定义变量,但是还是不明白,如何做任务。

答案1

不清楚您想要在序列中存储什么。但是您不应该将定义\NewDocumentCommand在较低级别expl3代码中的较高级别函数混合在一起。

\NewDocumentCommand上下文中定义的应该\ExplSyntaxOn只调用一个主要的内部函数和一些辅助函数,例如\group_begin:(这取决于许多因素,主要因素是避免代码重复)。

\documentclass{article}
\usepackage{xparse}
\usepackage{expl3}
\setlength{\parindent}{0cm}
\begin{document}
\ExplSyntaxOn
% The following three macros are well defined
\NewDocumentCommand{\newfpvar}{m}
 {
  \fp_new:N #1
 }
\NewDocumentCommand{\setfpvar}{mm}
 {
  \fp_set:Nn #1 { #2 }
 }
\NewDocumentCommand{\getfpvar}{m}
 {
  \fp_use:N #1
 }

% This one isn't well defined
%\NewDocumentCommand{\define_fp_var}{mm}{
%  \newfpvar{#1}
%  \setfpvar{#1}{#2}
%}

\cs_new_protected:Npn \mmmmxxxv_define_fp_var:Nn #1 #2
 {
  \cs_if_exist:NF #1
   {
    \fp_new:N #1
    \fp_set:Nn { #1 } { #2 }
   }
 }



%#1 - sequence name
%#2 - value
\cs_new_protected:Npn \mmmmxxxv_seq_put_fp_var_right:Nn #1 #2
 {
  \seq_put_right:Nx #1 { \fp_eval:n { #2 } }
 }

\seq_new:N \l_mmmmxxxv_fp_seq
\mmmmxxxv_seq_put_fp_var_right:Nn \l_mmmmxxxv_fp_seq { 1 }
\mmmmxxxv_seq_put_fp_var_right:Nn \l_mmmmxxxv_fp_seq { 2 }
\mmmmxxxv_seq_put_fp_var_right:Nn \l_mmmmxxxv_fp_seq { 3 }

\seq_map_inline:Nn \l_mmmmxxxv_fp_seq
 {
  #1\\
 }

\ExplSyntaxOff
\end{document}

这将打印

1
2
3

正如预期的那样。

您的代码在两个方面失败了。

  1. 用 定义的命令在函数的参数为​​以下情况\NewDocumentCommand时不会展开:x\seq_put_right:Nx

  2. 如果您以\seq_put_right:Nx小组形式进行此操作,则小组结束时作业将会消失。

答案2

用户命令应使用 的可能性来定义xparse。内部定义应由 和 朋友完成\cs_new:Npn。还有一个命名约定,即函数的最后一个标记代表参数的数量,函数名称的第一部分代表模块。抱歉,以 开头seq是错误的。有关规则的更多信息,请参阅 的文档expl3

与您的功能相关的\define_fp_var正确语法是:

\cs_new:Npn \user_define_fp_var:Nn #1 #2
 {
  \fp_new:N #1
  \fp_set:Nn #1 {#2}
}

符号N代表新的 fp 函数和n值。

相关内容