在这个问题中未使用给定的参数,因为#1
缺少..
人们实际上会认为会抛出一个错误或警告。
基于1:
\documentclass{article}
\usepackage{listings}
\lstnewenvironment{chat}[1][]{%
\renewcommand{\lstlistingname}{Chat}%
\xpatchcmd*{\lst@MakeCaption}{lol}{loc}{}{}%
\lstset{
backgroundcolor=\color{chatcolor}, #1 %<<-- if #1 is missing no warning or error is thrown.
}}{}
\begin{document}
\begin{chat}[caption={Talking...}]
user12: Hello World!
\end{chat}
\end{document}
答案1
这是 TeX 语言的一个特性:在定义宏时,你可以随意处理宏的参数,包括丢弃它们。可能最重要的一类例子是宏,例如\@ifundefined
:它的定义(大约)
\newcommand{\@ifundefined}[3]{%
\expandafter\ifx\csname #1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#2}{#3}%
}
(实际定义略有不同,但不是本质上的不同)。此宏依赖于\@firstoftwo
和\@secondoftwo
:
\newcommand{\@firstoftwo}[2]{#1}
\newcommand{\@secondoftwo}[2]{#2}
如您所见,两者的目的都是丢弃其中一个参数。当调用时\@ifundefined{abc}{def}{ghi}
,如果条件返回 true(因为\abc
未定义或等同于\relax
),TeX 将发现
\@firstoftwo{def}{ghi}
在输入流中,而它会查找\@secondoftwo{def}{ghi}
条件是否返回 false(因为\abc
具有与 不同的含义\relax
)。
我不希望每次\@firstoftwo
使用时都收到警告,但也不希望在定义时收到警告,因为我的目的正是定义\@firstoftwo
以丢弃它的一个参数。
此外,宏定义随时可能发生变化;在某些地方,一个参数宏被本地重新定义为不对其参数执行任何操作的情况并不少见。请查看\@gobble
以latex.ltx
查看几个示例。
TeX 与其他编程语言的区别之一是,TeX 主要针对处理文本. 与其他语言中的函数和例程不同,宏定义不是 TeX 的主要方面。当您这样做时\def
,TeX 只会将(参数文本和)替换文本存储在内存中,而不会进行任何类型的优化或精简。唯一的检查是使用的参数不超过声明的参数(并且括号是匹配的,)。
在编译型语言中,如果你定义两个函数来执行完全相同的操作,或者一个函数没有使用需要提供的变量之一,你很可能会收到警告,因为编译器能够进行深度词汇、语法和语义分析。然而,即使我们非正式地谈论“编译 LaTeX 文件”,TeX 也是一个解释器,而不是编译器。
吞噬输入通常是由解释型语言完成的。如果你在 Perl 或 Lua 中定义一个未使用其所有参数的函数,则不会收到任何警告:它可能是“一次性”函数,甚至是旨在在某些情况下丢弃部分输入的通用函数。