如何以 LaTeX3 方式使用 \csname\endcsname?

如何以 LaTeX3 方式使用 \csname\endcsname?

我有一些部分或代码是用LaTeX2e方法编写的。我想用LaTeX3方法重写它,但我不知道该怎么做。更多解释请参见 MWE

\documentclass[]{article}
\usepackage{xparse}

\newcounter{mycounter}
\setcounter{mycounter}{100}
% ======== Common way =======================
\def\daycell#1#2{\csname dc#1#2\endcsname}
\daycell{1}{2}
\expandafter\def\csname dc12\endcsname{\themycounter}

% =========== The LaTeX3 way =======================
\ExplSyntaxOn


\cs_new:Npn \DayCell {#1#2} {\cs:w dc#1#2 \cs_end:} % I have no idea


\ExplSyntaxOff

\begin{document}

\daycell{1}{2}

\end{document}

添加以澄清

\documentclass[]{article}

\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \sergiokapone_daycell:nn #1 #2
  {
    \use:c { dc #1 #2 }
  }
\cs_new_protected:Npn \sergiokapone_set_daycell:nnn #1 #2 #3
  {
    \cs_set:cpn { dc #1 #2 } { #3 }
  }
\NewDocumentCommand \SetDayCell { mmm }
  {
    \sergiokapone_set_daycell:nnn { #1 } { #2 } { #3 }
  }
\NewExpandableDocumentCommand \DayCell { m m }
  {
    \sergiokapone_daycell:nn { #1 } { #2 }
  }

\DeclareDocumentCommand\Replicate{ m    m }{%
    \prg_replicate:nn {#1} {#2} 
}

\ExplSyntaxOff

\begin{document}

% ======== desired result (it is work) ========
% Temporary commented
%---- Here \SetDayCell{i}{j}{some number}
%\SetDayCell{1}{1}{1}
%\SetDayCell{1}{2}{2}
%\SetDayCell{1}{3}{3}
%\SetDayCell{1}{4}{4}
%\SetDayCell{1}{5}{5}
% I get what I want  1 2 3 4 5

% ======= I want to just replicate example from above ===
% But it work incorrect
\newcounter{C}
\setcounter{C}{1}
\Replicate{5}{
\SetDayCell{1}{\theC}{\theC}
\stepcounter{C}
}
% I get 6 6 6 6 6

% ==== cell's filling ==== 
\newcounter{var}
\setcounter{var}{1}
\Replicate{5}{
\DayCell{1}{\thevar}
\stepcounter{var}
}


\end{document}

答案1

执行此操作的标准方法是提供\DayCell使用:c参数的函数的变体,如果它只是一个应该转换为控制序列的参数。

另请注意,语句中的参数\cs_new:Npn不允许包含括号(它的语法或多或少与 TeX 的语法相同\def)。

使用和类似方法创建的内部函数\cs_new:Npn应始终包含参数类型作为其名称的一部分,因此对于采用两个括号参数的宏,您应该具有诸如的名称\<module>_<name>:nn,函数应始终遵循该命名方案\<module>_<name>:<args>

此外,如果不是绝对必要,您应该使用更高级别的函数将某些东西转换为宏名,因此只有在绝对必要时才使用\cs:w\cs:end,例如,因为 begin 和 end 在两个不同的宏中,否则您应该使用\use:c

此外,\cs_new:Npn和类似的仅应用于内部功能,文档/用户级别功能应使用\NewDocumentCommand或类似的来定义。

将以上所有内容转化为一些代码:

\documentclass[]{article}

\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn \sergiokapone_daycell:nn #1 #2
  {
    \use:c { dc #1 #2 }
  }
\cs_new_protected:Npn \sergiokapone_set_daycell:nnn #1 #2 #3
  {
    \cs_set:cpn { dc #1 #2 } { #3 }
  }
\NewDocumentCommand \SetDayCell { mmm }
  {
    \sergiokapone_set_daycell:nnn { #1 } { #2 } { #3 }
  }
\NewExpandableDocumentCommand \DayCell { m m }
  {
    \sergiokapone_daycell:nn { #1 } { #2 }
  }

\ExplSyntaxOff

\begin{document}
\SetDayCell{1}{2}{100}
\DayCell{1}{2}
\end{document}

答案2

你的代码有几个问题。我先分析一下“传统”代码。

如果你\expandafter\def\csname dc#1#2\endcsname{\themycounter}这样做惯于执行 后将得到 100 \daycell{1}{2},除非 的值mycounter在此期间没有改变。您应该使用\edef

至于expl3实施方面,这似乎需要一个属性清单。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\setdaycell}{mmm}
 {
  \sergio_daycell_set:nne { #1 } { #2 } { #3 }
 }
\NewExpandableDocumentCommand{\daycell}{mm}
 {
  \prop_item:Nn \l_sergio_daycell_prop { #1#2 }
 }

\prop_new:N \l_sergio_daycell_prop

\cs_new_protected:Nn \sergio_daycell_set:nnn
 {
  \prop_put:Nnn \l_sergio_daycell_prop { #1#2 } { #3 }
 }
\cs_generate_variant:Nn \sergio_daycell_set:nnn { nne }

\ExplSyntaxOff

\newcounter{mycounter}

\begin{document}

\setcounter{mycounter}{100}

\setdaycell{1}{2}{\themycounter}

\setcounter{mycounter}{42}

\daycell{1}{2}

\end{document}

这将打印 100。


看了你的例子后,很明显你在扩展方面存在一些问题,类似于上面第二段所描述的。

您可以通过在适当的时候强制扩展来实现这一点。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

%%% for the example
\NewDocumentCommand{\replicate}{mm}
 {
  \prg_replicate:nn { #1 } { #2 }
 }
%%%%%%%%

\NewDocumentCommand{\setdaycell}{mmm}
 {
  \sergio_daycell_set:nne { #1 } { #2 } { #3 }
 }
\NewExpandableDocumentCommand{\daycell}{mm}
 {
  \prop_item:Ne \l_sergio_daycell_prop { #1#2 }
 }

\cs_generate_variant:Nn \prop_put:Nnn { Nx }
\cs_generate_variant:Nn \prop_item:Nn { Ne }
\prop_new:N \l_sergio_daycell_prop

\cs_new_protected:Nn \sergio_daycell_set:nnn
 {
  \prop_put:Nxn \l_sergio_daycell_prop { #1#2 } { #3 }
 }
\cs_generate_variant:Nn \sergio_daycell_set:nnn { nne }

\ExplSyntaxOff

\begin{document}

\newcounter{C}
\setcounter{C}{1}
\replicate{5}{%
  \setdaycell{1}{\theC}{\theC}%
  \stepcounter{C}%
}
% I get 6 6 6 6 6

% ==== cell's filling ==== 
\newcounter{var}
\setcounter{var}{1}
\replicate{5}{%%
  \daycell{1}{\thevar}%
  \stepcounter{var} % <- space is wanted
}

\end{document}

这将正确打印“1 2 3 4 5”

相关内容