我是 TeX 和 LaTeX 的新手,在定义和使用定义其他宏的宏时遇到了麻烦。我读过如何做到这一点(例如,https://en.wikibooks.org/wiki/LaTeX/Plain_TeX#Plain_TeX_macros,以及本网站上之前的各种问题),但我就是无法让它工作。
考虑以下故意冗长的代码片段:
\def\apcodeEWR {EWR}
\def\apnameEWR {Newark Liberty International Airport}
\def\apcityEWR {Newark, NJ, USA}
\def\apcodeORY {ORY}
\def\apnameORY {Paris Orly Airport}
\def\apcityORY {Orly, France}
\def\apdescriptionEWR {\apnameEWR, located in \apcityEWR, has the airport code \apcodeEWR.}
\def\apdescriptionORY {\apnameORY, located in \apcityORY, has the airport code \apcodeORY.}
\begin{itemize}
\item \apdescriptionEWR
\item \apdescriptionORY
\end{itemize}
这将输出我期望的结果:
* Newark Liberty International Airport, located in Newark, NJ, USA, has the airport code EWR.
* Paris Orly Airport, located in Orly, France, has the airport code ORY.
但我想做类似的事情:
\apdefine{EWR}{Newark Liberty International Airport}{Newark, NJ, USA}
\apdefine{ORY}{Paris Orly Airport}{Paris, France}
\begin{itemize}
\apdescribe{EWR}
\apdescribe{ORY}
\end{itemize}
我想首先克服这个障碍,但我觉得我应该提一下,最终我真的很想做这样的事情:
\begin{itemize}
\foreachairport\apdescribe
\end{itemize}
因此,现在我正在尝试制作那个“apdefine”宏。根据我之前链接的书,我正在尝试这个(之前尝试过很多其他方法):
\def\apdefine#1#2#3 {
\expandafter\def\csnameapcode#1\endcsname {##1}
\expandafter\def\csnameapname#1\endcsname {##2}
\expandafter\def\csnameapcity#1\endcsname {##3}
}
编译没有错误。但是我尝试使用它:
\apdefine{IBA}{Ibadan Airport}{Ibadan, Oyo, Nigeria}
我收到九个错误,全部在该行。它们是以下三组:
Undefined control sequence. ...IBA}{Ibadan Airport}{Ibadan, Oyo, Nigeria}
Missing control sequence inserted. ...IBA}{Ibadan Airport}{Ibadan, Oyo, Nigeria}
Illegal parameter number in definition of \inaccessible. ...IBA}{Ibadan Airport}{Ibadan, Oyo, Nigeria}
我做错了什么?我该如何正确做?或者,如果有一种完全不同的方法可以用来做我想做的事情,那是什么?谢谢。
答案1
调用\apdefine
定义三个参数变量以及描述变量。然后,它将机场代码附加到名为 的逗号分隔列表中\airportlist
。
通过 定义每个机场后\apdefine
,应该调用\readlist
,这将创建一个listofitems
名为 的数组\airports
,可以方便地在循环中使用\foreachitem
。
\documentclass{article}
\usepackage{listofitems}
\ignoreemptyitems
\def\airportlist{}
\newcommand\apdefine[3]{%
\expandafter\def\csname apcode#1\endcsname{#1}%
\expandafter\def\csname apname#1\endcsname{#2}%
\expandafter\def\csname apcity#1\endcsname{#3}%
\expandafter\def\csname apdescription#1\endcsname{%
#2, located in #3, has the airport code #1.}%
\expandafter\def\expandafter\airportlist\expandafter{\airportlist#1,}
}
\apdefine{EWR}{Newark Liberty International Airport}{Newark, NJ, USA}
\apdefine{ORY}{Paris Orly Airport}{Paris, France}
\apdefine{IBA}{Ibadan Airport}{Ibadan, Oyo, Nigeria}
\readlist\airports{\airportlist}
\begin{document}
\begin{itemize}
\foreachitem\z\in\airports[]{\item \csname apdescription\z\endcsname}
\end{itemize}
\end{document}
答案2
您可以使用prop
列表来expl3
存储每个条目的相关数据,然后将每个条目的键存储在列表中。定义一个以文本为参数的seq
命令,您可以循环遍历列表并打印文本。\apdescribetext
seq
\apdefine
接受三个参数:机场代码、名称和地址。
\apdescribe
接受机场代码作为参数并使用打印其信息\apdescribetext
。
\apdescribeall
循环遍历机场列表并打印每一个机场。
代码如下:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \g_vesterman_airports_seq
\NewDocumentCommand \apdefine { mmm }
{
\seq_gput_right:Nn \g_vesterman_airports_seq {#1}
\prop_new:c { g_vesterman_#1_prop }
\prop_gput:cnn { g_vesterman_#1_prop } { name } {#2}
\prop_gput:cnn { g_vesterman_#1_prop } { address } {#3}
}
\NewDocumentCommand \apdescribe { m }
{
\exp_args:Nff \apdescribetext
{ \prop_item:cn { g_vesterman_#1_prop } { name } }
{ \prop_item:cn { g_vesterman_#1_prop } { address } }
{#1}
}
\NewDocumentCommand \apdescribeall { }
{ \seq_map_function:NN \g_vesterman_airports_seq \apdescribe }
\ExplSyntaxOff
\newcommand{\apdescribetext}[3]{\item #1, located in #2, has the airport code #3.}
\apdefine{EWR}{Newark Liberty International Airport}{Newark, NJ, USA}
\apdefine{ORY}{Paris Orly Airport}{Paris, France}
\begin{document}
\begin{itemize}
\apdescribeall
\end{itemize}
\end{document}