我得到了这个 Tex 命令,作为解决另一个问题并且它确实有效。但我很难理解它的工作原理,因为我对 Latex 编码不是很熟练,而且我想学习。
%\DTLfetchifnull{<db name>}%
% {<column1 name>}%
% {<column1 value>}%
% {<column2 name>}%
% {<tokens in case <column2-value> is not a null-value>}%
% {<tokens in case <column2-value> is a null-value>}%
% {<tokens in case <column1-value> does not exist>}%
%
% Both with <tokens in case <column2-value> is not a null-value> and with
% <tokens in case <column2-value> is a null-value> the macro
% \dtlcurrentvalue is defined to yield the value of the column whose name
% is <column2 name>.
%
\makeatletter
\@ifundefined{NewDocumentCommand}%
{\newcommand\DTLfetchifnull[7]}%
{\NewDocumentCommand\DTLfetchifnull{mmmmmmm}}%
{%
\begingroup%
\protected@edef\@dtl@dogetrowforvalue{%
\noexpand%
\endgroup
\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue%
\ifx \dtl@rowidx\dtlnovalue%
\expandafter\@secondoftwo%
\else%
\expandafter\@firstoftwo%
\fi%
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}%
\makeatother
- 据我所知,\makeatletter ... \makeatother 是必要的,因为我们改变了 NewDocumentCommand 和 newcommand 的一些基本内容?
- @ifundefined{NewDocumentCommand}% 据我所知,是否可以在没有 \usepackage{xparse} 的情况下使用 NewDocumentCommand 而不是 newcommand?
我们为什么需要这个?我们可以只使用 \usepackage{xparse} 并跳过整个步骤吗:
\makeatletter
\@ifundefined{NewDocumentCommand}%
{\newcommand\DTLfetchifnull[7]}%
...
\makeatother
或者这样做有什么好处吗?
\begingroup ... \endgroup 据我所知,它类似于 '{ }',但行为不同
但是它包围了“\protected@edef@dtl@dogetrowforvalue{”,所以“}”在外面,这是怎么回事?
\begingroup% \protected@edef@dtl@dogetrowforvalue{% \noexpand% \endgroup \noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}% }@dtl@dogetrowforvalue%
我发现很难读懂这些函数是如何封装的,也很难决定哪个是哪个函数的参数或者只是跟在函数后面。
这表示检查 if(\dtl@rowidx\dtlnovalue) do \expandafter@secondoftwo else \expandafter@firstoftwo。
\ifx \dtl@rowidx\dtlnovalue
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
@firstoftwo 和 @secondoftwo 是紧随其后的花括号内的两个选项吗?
答案1
\makeatletter
并且\makeatother
是必需的,以便允许@
在其中使用命令名称。这没什么特别的。
第一个想法是,如果可用就使用它,否则就使用\NewDocumentCommand{\DTLfetchifnull}{mmmmmmm}
标准(为了与旧文档兼容)。\newcommand{\DTLfetchifnull}[7]
随着新版本的发布,我们基本上得到了
\NewDocumentCommand\DTLfetchifnull{mmmmmmm}
{%
\begingroup%
\protected@edef\@dtl@dogetrowforvalue{%
\noexpand%
\endgroup
\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue%
\ifx \dtl@rowidx\dtlnovalue%
\expandafter\@secondoftwo%
\else%
\expandafter\@firstoftwo%
\fi%
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}%
这表明编程风格不太好。例如,有几个无用的%
,但它们没有危害,只是令人讨厌。而且第一个\noexpand
是无用的,因为`\endgroup 不可扩展。我会把它写成
\NewDocumentCommand\DTLfetchifnull{mmmmmmm}
{%
\begingroup
\protected@edef\@dtl@dogetrowforvalue{%
\endgroup
\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
}\@dtl@dogetrowforvalue
\ifx \dtl@rowidx\dtlnovalue
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
{%
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
}{%
#7%
}%
}
如果是旧版 LaTeX 则第一行应该是\newcommand{\DTLfetchifnull}[7]
。
这个想法是定义\@dtl@dogetrowforvalue
产生
\endgroup
\dtlgetrowindex{\dtl@rowidx}
{expansion of #1}
{expansion of \dtlcolumnindex{#1}{#2}}
{expansion of #3}
然后\@dtl@dogetrowforvalue
将执行临时宏,它将为 赋予一个含义\dtl@rowidx
,能是\dtlnovalue
(取决于参数#1
,#2
和#3
。初始\endgroup
将平衡已经消化的\begingroup
,并且的定义\@dtl@dogetrowforvalue
将在执行后立即被遗忘\endgroup
(但的扩展\@dtl@dogetrowforvalue
已经放置在输入流中,因此取消定义它没有问题)。
接下来将 token 与 进行比较\dtlnovalue
。构造
\if<something>
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
{tokens A}
{tokens B}
在 LaTeX 编程中非常常见。如果测试返回 true,tokens B
则使用 ,否则使用tokens A
。
因此,如果\dtl@rowidx
结果是\dtlnovalue
,则将使用该参数#7
。否则它将是某个合法的行索引和
\edtlgetrowforvalue{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#1}{#4}}%
\DTLifnull{\dtlcurrentvalue}{#6}{#5}%
将会被使用。找出什么这确实需要学习的手册datatool
。