\def 的问题

\def 的问题

有人能告诉我为什么这有效吗

\documentclass{article}


\usepackage{etoolbox}


\newcounter{mylistcounter}
\newcommand{\getnthelement}[2]{
\setcounter{mylistcounter}{1}
\renewcommand*\do[1]{
    \ifnumequal{\value{mylistcounter}}{#1}{##1\listbreak}\relax
    \stepcounter{mylistcounter}}
\dolistloop{#2}}

\def\SerieID{HA}
\listadd\IDlist{HA}
\csgdef{\SerieID.DeckblattDatei}{test (HA)}

\def\SerieID{PR}
\listadd\IDlist{PR}
\csgdef{\SerieID.DeckblattDatei}{test (PR)}



\begin{document}
\def\SerieID{HA}
\csuse{\SerieID.DeckblattDatei}




\end{document}

但如果我把 \def 命令改为

\def\SerieID{\getnthelement{1}{\IDlist}}

我收到 \endcsname 错误

答案1

重新定义\getnthelement采用第三个参数,作为包含搜索结果的宏的名称。

\newcommand{\getnthelement}[3]{%
\setcounter{mylistcounter}{1}%
\renewcommand*\do[1]{%
    \ifnumequal{\value{mylistcounter}}{#1}{\def#3{##1}\listbreak}\relax
    \stepcounter{mylistcounter}}%
\dolistloop{#2}}

注意使用%以避免引入虚假空格。

用法:

\getnthelement{1}{\IDlist}\SerieID
\csuse{\SerieID.DeckblattDatei}

但是,这个解决方案很脆弱:搜索返回的材料应该是可扩展的,否则\csuse会再次出现错误。此外,如果搜索失败(因为列表太短),\SerieID则将未定义或包含一些旧值。

答案2

你可以使用序列,而不用etoolbox列表,因为列表很难获取项目expl3

\documentclass{article}
\usepackage{etoolbox}

\ExplSyntaxOn

\NewDocumentCommand{\definelist}{m}
 {
  \seq_new:c { l_gaweiliex_list_#1_seq }
 }

\NewDocumentCommand{\addtolist}{mm}
 {
  \seq_put_right:cn { l_gaweiliex_list_#1_seq } { #2 }
 }

\NewExpandableDocumentCommand{\getfromlist}{mm}
 {% #1 = list name
  % #2 = item number
  \seq_item:cn { l_gaweiliex_list_#1_seq } { #2 }
 }

\ExplSyntaxOff

\definelist{IDlist}
\addtolist{IDlist}{HA}
\csdef{HA.DeckblattDatei}{test (HA)}

\addtolist{IDlist}{PR}
\csdef{PR.DeckblattDatei}{test (PR)}

\begin{document}

\edef\SerieID{\getfromlist{IDlist}{1}}
\csuse{\SerieID.DeckblattDatei}

\edef\SerieID{\getfromlist{IDlist}{2}}
\csuse{\SerieID.DeckblattDatei}

\end{document}

在此处输入图片描述

相关内容