命令钩子与包钩子,哪个更好?

命令钩子与包钩子,哪个更好?

在为我的包设计钩子接口时,我发现我有两种定义钩子的方法:

\documentclass{article}

\begin{document}

\section*{Method 1: Use Command Hooks}

\NewDocumentCommand\MyPkgSomeHook{}{}

\AddToHook{cmd/MyPkgSomeHook/before}{hello}
\AddToHook{cmd/MyPkgSomeHook/before}{world}

\UseHook{cmd/MyPkgSomeHook/before}

\section*{Method 2: Use Package Hooks}

\NewHook{mypkg/somehook}

\AddToHook{mypkg/somehook}{hello}
\AddToHook{mypkg/somehook}{world}

\UseHook{mypkg/somehook}

\end{document}

哪种方法更好(速度和其他方面)?

答案1

通用钩子(例如cmdhooks)用于非常特定的地方(cmd调用命令时使用钩子),不应在其他地方手动使用。没有什么可以阻止你这样做,但这可能会造成混淆。通用钩子的定义(当你这样做时它们是隐式定义的\AddToHook{some/generic/hook})与它们的用法(在另一个命令或环境中自动使用)不同,所以你不应该把它当作普通钩子来使用。

第二个选项是正确的:您创建一个名为的普通钩子mypkg/something,并将其与一起正常使用\UseHook

此外,使用mypkg/somehook比使用通用钩子要快一点,cmd因为后者尝试修补命令\begin{document},这需要一些(可忽略的)时间,所以没有理由滥用通用cmd钩子。


警告

cmd当然,通用钩子的存在是有原因的!假设你写了一个用于排版表格的漂亮包,并且你有一个这样的命令:

\NewDocumentCommand \MagicTable { m m }
  {
    \begin{tabular}{rl}
      #1 & #2 \\
    \end{tabular}
  }

(我知道这并不令人印象深刻 :) 并且您想要提供一个钩子来为该令人印象深刻的表格添加标题。如果用户刚刚这样做\AddToHook{cmd/MagicTable/before}{<header>},内容将放在表格环境之外,显然不起作用。然后您可以为此类用户提供:

\NewDocumentCommand \MagicTable { m m }
  {
    \begin{tabular}{rl}
      \UseHook{cmd/MagicTable/before}
      #1 & #2 \\
    \end{tabular}
  }
\NewHook{cmd/MagicTable/before}

在这种情况下,您可以“使通用钩子变得正常”,并且钩子系统不会尝试修补该钩子,\MagicTable因为您已经告诉它该钩子存在(通过执行\NewHook)。

这个例子有点明显,因为表格材料在表格环境之外根本不起作用,但在其他情况下,包作者可以在人们使用这样的钩子之后微调cmd/.../before和钩子的位置。cmd/.../after

但是如果您提供的新功能不是简单的“在该命令之前运行这堆代码”,那么正确的替代方法是使用普通的钩子名称。

相关内容