Definir macros

Cuando te descubres escribiendo lo mismo una y otra vez, o sabes que querrás cambiarlo en todas partes más adelante, defines tu propio comando, una macro. La base es \newcommand. Esta página recorre los fundamentos: tomar argumentos, redefinir comandos existentes, el moderno \NewDocumentCommand y la práctica de evitar comandos “frágiles”.

Definir comandos con \newcommand

La herramienta más básica es \newcommand{\name}{definition}. El primer argumento es el nombre del comando que quieres y el segundo lo que representa. Si escribes el nombre de tu grupo de investigación muchas veces, defínelo una vez en el preámbulo; después, \name en el texto se expande a definition.

latex
% プリアンブルで定義 / define in the preamble
\newcommand{\grp}{Knuth Typesetting Lab}

% 本文で使う / use it in the body
Welcome to the \grp. The \grp{} was founded in 1978.

Observa los {} después del segundo \grp. Un comando formado por letras, como \grp, se come el espacio que viene justo después como separador del nombre. Por eso \grp was pierde el espacio y produce “Labwas” en lugar de “Lab was”. La solución estándar es un par de llaves vacío {} para marcar dónde acaba el nombre; consulta “Reglas de sintaxis”.

Regla clave: \newcommand tiene éxito solo si ese nombre aún no está definido. Usarlo con un nombre existente, incluidos comandos del núcleo o de paquetes, se detiene con Command \name already defined. Es una red de seguridad deliberada contra sobrescribir silenciosamente. Para rehacer un comando existente a propósito, usa \renewcommand.

Macros que toman argumentos

Para variar el contenido en cada llamada, da argumentos al comando. Escribe el número de argumentos entre corchetes después del nombre — \newcommand{\name}[⟨nargs⟩]{... #1 #2 ...} — y refiérete a ellos dentro de la definición como #1, #2, etc. Los parámetros van de #1 a #9, nueve como máximo.

latex
\newcommand{\unit}[2]{#1\,\mathrm{#2}}

% \unit{9.8}{m/s^2} → 9.8 m/s^2(数と単位の間に細い空き)
$a = \unit{9.8}{m/s^2}$

También puedes hacer opcional el primer argumento, con un valor por defecto. Al duplicar los corchetes — \newcommand{\name}[⟨nargs⟩][⟨default⟩]{...}#1 se vuelve opcional y su valor por defecto es ⟨default⟩. Lo llamas como \name (usa el valor por defecto) o \name[x] (#1 pasa a ser x); los obligatorios restantes empiezan en #2.

latex
% 全 2 引数、うち #1 は省略可能で既定値 2
\newcommand{\plusbinomial}[2][2]{(x + y)^{#1}_{#2}}

$\plusbinomial{n}$      % → (x + y)^2_n   (#1 は既定の 2)
$\plusbinomial[3]{n}$   % → (x + y)^3_n   (#1 を 3 に)

Cuida cómo se cuentan los corchetes: el ⟨nargs⟩ de [⟨nargs⟩] es el número total de argumentos, incluido el opcional. Así, el ejemplo significa “dos argumentos, el primero opcional”. Además, omitir [⟨default⟩] no es lo mismo que escribir []: esto último da un argumento opcional cuyo valor por defecto es la cadena vacía.

Redefinir, proporcionar y hacer robusto

\newcommand tiene tres parientes con propósitos distintos. Todos toman argumentos igual ([⟨nargs⟩][⟨default⟩]); lo que cambia es cómo se comportan ante un nombre ya definido.

ComandoAnte un nombre existenteUso principal
\newcommandSe detiene con errorCrear un comando nuevo con seguridad
\renewcommandLo sobrescribe (error si no existe)Rehacer un comando existente
\providecommandNo hace nada (mantiene el anterior)Archivos de estilo que pueden cargarse dos veces
\DeclareRobustCommandSobrescribe y deja nota en el logComandos robustos para argumentos móviles

\renewcommand redefine un comando existente. Es el espejo de \newcommand: el objetivo debe estar ya definido o dará error. Lo usas para sustituir el contenido de un comando que LaTeX ya proporciona, por ejemplo el símbolo de una lista.

latex
% itemize の第 1 階層の記号をダッシュに
\renewcommand{\labelitemi}{--}

% 既存マクロを新しい中身で作り直す
\renewcommand{\grp}{Lamport Typesetting Lab}

\providecommand define un comando solo si aún no existe. Si el nombre está indefinido, se comporta exactamente como \newcommand; si ya existe, no hace nada y conserva la definición existente, sin error. Encaja con archivos de estilo que podrían cargarse más de una vez.

\DeclareRobustCommand construye un comando robusto incluso si su interior contiene código frágil. A diferencia de \newcommand, no da error sobre un nombre existente; al redefinirlo, solo escribe una nota en el log. Los comandos así creados son algo menos eficientes, así que úsalo solo cuando el contenido sea frágil y aparezca en argumentos móviles; si no, prefiere \newcommand.

Comandos frágiles y \protect

LaTeX tiene un contexto especial llamado argumento móvil. El título de \section{...} no solo se compone en el cuerpo: también se escribe en la tabla de contenidos, la cabecera y el archivo auxiliar .aux, moviéndose a varios lugares. El contenido de \caption{...}, \thanks{...} y las expresiones @{...} de tabular/array también son argumentos móviles.

Un comando que se rompe en TeX inválido al expandirse en ese contexto se llama comando frágil; uno que sobrevive, comando robusto. El remedio clásico es poner \protect justo antes de un comando frágil para decir a LaTeX: “no lo expandas aquí, escríbelo tal cual”. La protección es por comando: cada \protect protege solo el comando siguiente.

latex
% 可動引数の中で壊れやすい \verb を保護する
\section{The \protect\verb|\par| primitive}

Hay buenas noticias: desde LaTeX de octubre de 2019, muchos comandos antes frágiles se hicieron robustos. Comandos con argumentos opcionales como \raisebox, y las matemáticas en línea \(...\), pueden ir hoy en un título sin \protect. El caso que más queda es \verb, que a menudo ni \protect salva; en títulos o leyendas suele ser más rápido reescribirlo con \texttt{...}. Al definir tus propias macros, usar \DeclareRobustCommand desde el principio elimina esa preocupación.

El moderno \NewDocumentCommand

LaTeX moderno ofrece otra forma más potente de definir comandos: \NewDocumentCommand{\name}{⟨arg-spec⟩}{...}. Originalmente era una función del paquete xparse, pero ahora forma parte del núcleo de LaTeX (ltcmd) y está disponible sin \usepackage. En lugar de escribir un número de argumentos, declaras una especificación de argumentos (arg-spec): una cadena de letras que nombra el tipo de cada argumento.

EspecificadorSignificadoCómo llega al cuerpo
mArgumento obligatorioUn argumento ordinario como #1
oArgumento opcional [...]Marcador de “sin valor” si falta
O{default}Opcional con valor por defectodefault si falta
sEstrella opcional *Se prueba con \IfBooleanTF

Es más potente que \newcommand por dos razones: puede tomar varios argumentos opcionales y maneja correctamente variantes con estrella. El ejemplo de abajo ramifica según la estrella con \IfBooleanTF (#1 es la estrella, #2 el argumento obligatorio). Para código nuevo, esta interfaz moderna es la recomendada; la página de xparse la cubre en detalle.

latex
\NewDocumentCommand{\diff}{s m}{%
  \IfBooleanTF{#1}%
    {\frac{\mathrm{d}}{\mathrm{d}#2}}%   星つき: d/dx 形
    {\mathrm{d}#2}%                      星なし: dx 形
}

$\diff{x}$    % → dx
$\diff*{x}$   % → d/dx

Buenas prácticas de macros

Las macros brillan sobre todo como macros semánticas. Nombrar las cosas por lo que son —los reales como \newcommand{\R}{\mathbb{R}}, la d diferencial como \newcommand{\dd}{\mathrm{d}}— mantiene la notación coherente en todo el documento. Si luego quieres cambiar el aspecto, basta editar una línea de definición.

latex
\newcommand{\R}{\mathbb{R}}
\newcommand{\dd}{\mathrm{d}}

% 統一された表記で書ける / write with consistent notation
$\int_{\R} f(x)\,\dd x$

Dicho eso, demasiadas macros dañan la legibilidad. Una abreviatura extrema como \newcommand{\x}{\xi} puede volverse un cifrado para tu yo futuro o un coautor meses después. Reserva las macros para lo que se repite a menudo, probablemente cambiará en bloque o merece nombre por significado; para lo demás, escribirlo directamente suele ser más legible.

Por último, evita choques de nombres. No sobrescribas a la ligera comandos del núcleo o de paquetes con \renewcommand: los efectos secundarios pueden sorprenderte. Para tus comandos, evita nombres demasiado cortos y prefiere un prefijo propio del proyecto (\myR, \bookTitle). En caso de duda, define primero con \newcommand; un error already defined te dice que el nombre ya está tomado.