如何编写采用可变数量参数的宏

如何编写采用可变数量参数的宏

我正在尝试创建一个名为 的新命令,\com它可以执行以下操作:

  • 如果没有提供参数\com,则$\com$生成符号$\lambda$
  • 如果提供了一个参数,例如$\com{f}$,则宏会产生$\lambda [f]$(带方括号)。
  • 如果提供了两个参数,例如$\com{f}{x}$,宏会产生符号$\lambda {f}(x)$(分别带有花括号和圆括号)。

我尝试过其他帖子中的 if else 命令,但无法使其工作。

如果有人能告诉我如何做到这一点,我将不胜感激。

答案1

这很容易xparse\NewDocumentCommand,有两个可选参数,但是,您需要检查它们是否存在。

请注意,oo可以用 来替换以gg允许可选{}{}参数,但不建议这样做,但请参阅下面的答案作为替代。

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\com}{oo}{%
  \lambda%
  %Check if the first arg is given
  \IfValueT{#1}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#2}{% Yes, the 2nd one is present, use {f}(x) style
      \{#1\}(#2)%
    }{% No, use [f] style
      [#1]% 
    }%
  }%
}

\begin{document}

$\com$

$\com[f]$

$\com[f][x]$

\end{document}

在此处输入图片描述

使用gg类型更新(请小心使用!)并使用另一个可选参数来代替\lambda

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\com}{oo}{%
  \lambda%
  %Check if the first arg is given
  \IfValueT{#1}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#2}{% Yes, the 2nd one is present, use {f}(x) style
      \{#1\}(#2)%
    }{% No, use [f] style
      [#1]% 
    }%
  }%
}

\NewDocumentCommand{\comother}{O{\lambda}gg}{%
  #1%
  %Check if the first arg is given
  \IfValueT{#2}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#3}{% Yes, the 2nd one is present, use {f}(x) style
      \{#2\}(#3)%
    }{% No, use [f] style
      [#2]% 
    }%
  }%
}


\begin{document}

$\com$

$\com[f]$

$\com[f][x]$


$\comother$

$\comother{f}$

$\comother{f}{x}$

% Now with \beta instead of \lambda

$\comother[\beta]$

$\comother[\beta]{h}$

$\comother[\beta]{h}{y}$
\end{document}

在此处输入图片描述

答案2

当然,语法使用标准 LaTeX 约定,将可选参数放在方括号中,在本例中是两个可选参数。

此外,OP 暗示应该使用命令不是在数学模式中,所以我已经适应了这一点。

\documentclass{article}
\newcommand\com[1][\relax]{\ifx\relax#1$\lambda$\else\def\firstarg{#1}\comhelp\fi}
\newcommand\comhelp[1][\relax]{\ifx\relax#1$\lambda [\firstarg]$%
  \else$\lambda \{\firstarg\}(#1)$\fi}
\begin{document}
\com\quad\com[f]\quad\com[f][x]
\end{document}

在此处输入图片描述

对于以数学模式运行的版本,如下所示:

\documentclass{article}
\newcommand\com[1][\relax]{\ifx\relax#1\lambda\else\def\firstarg{#1}\comhelp\fi}
\newcommand\comhelp[1][\relax]{\ifx\relax#1\lambda [\firstarg]%
  \else\lambda \{\firstarg\}(#1)\fi}
\begin{document}
$\com\quad\com[f]\quad\com[f][x]$
\end{document}

答案3

这是一个基于 LuaLaTeX 的解决方案。它充当预处理器:Lua 函数comscan在处理的早期阶段运行,TeX 开始做它的日常工作。Lua 函数查找所有实例\com并用不同的宏替换,具体取决于\com发现是否有 0、1 或 2 个参数。

在此处输入图片描述

% !TeX program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function comscan ( s )
  s = string.gsub ( s , "\\com(%b{})(%b{})" , "\\lambda\\{%1\\}(%2)" )
  s = string.gsub ( s , "\\com(%b{})", "\\lambda[%1]" )
  s = string.gsub ( s , "\\com(%A)" , "\\lambda%1" )
  return ( s )
end
luatexbase.add_to_callback( "process_input_buffer", comscan, "comscan" )
\end{luacode}
\providecommand{\command}{aaa} % dummy command
\begin{document}
$\com{f}{x}$, $\com{g}$, $ \com $, \command
\end{document}

答案4

由于您将使用非标准参数,我认为您可以尝试编写更易于阅读的代码。这样可以[f]输出括号、{f}输出花括号(在这里您可以避免输入\{f\})并(f)输出圆括号。

使用这段最少的代码,您可以确保\com\com[f]并且\com{f}(g)行为符合您的预期(赋予命令的唯一智能是转换{f}\{f\},其余部分保持不变并按您的预期工作)。

\usepackage{xparse}
\NewDocumentCommand\com{g}{\lambda\IfValueT{#1}{\{#1\}}}

如果你真的需要将它们视为参数,并且需要更多的智能,那么你需要定义完整的命令

\NewDocumentCommand\com{o}{\lambda\IfValueTF{#1}{[#1]}{\comaux}}
\NewDocumentCommand\comaux{gd()}{\IfValueT{#2}{\{#1\}}\IfValueT{#2}{(#2)}}

相关内容