Definición de una macro con múltiples argumentos y uso de \csname

Definición de una macro con múltiples argumentos y uso de \csname

¿Por qué el siguiente código no funciona?

\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
    \NewEnviron{\csname #1\endcsname}[1]{%
        ##1 : \BODY
    }
}

He visto ejemplos del uso de \csname SOMENAME\endcsnamefor macro sin argumentos pero no sé cómo hacerlo con a \NewEnvirono \newcommandcon múltiples argumentos. Me aparece el error ! Missing \endcsname inserted.

Respuesta1

No desea un nombre de comando para el nombre de un entorno. Sólo el nombre está bien.

Entonces, puedes hacer esto:

\documentclass{article}
\usepackage{amsthm,environ}
\renewcommand\newtheorem[2]{%
    \NewEnviron{#1}[1]{%
        ##1 : \BODY
    }%
}
\begin{document}
\newtheorem{acorns}{oaks}
\begin{acorns}{trees}
  leaves and things
\end{acorns}
\end{document}

Tenga en cuenta que este código no requiereamstmo, podría usarlo \newcommand\newtheorem...a menos que necesite el paquete por otros motivos.

Además, nunca hace nada con el segundo argumento, aunque cree el comando para que sea necesario. En el ejemplo anterior, nunca se hace nada con oaks.

No estoy convencido de que esto sea realmente lo que quieres hacer. El resultado del código anterior es:

árboles y hojas y cosas

ComoChristian Hupfer señala, esto, por supuesto, romperá cualquier cosa que se use \newtheoremen el sentido estándar. Comoegreg dice, no está del todo claro para qué \newtheoremsirve una redefinición de este tipo. Parece casi seguro que causará problemas tarde o temprano... probablemente antes.

Respuesta2

¿Por qué el siguiente código no funciona?

Echemos un vistazo más de cerca a lo que \NewEnvironhace:

Después de una breve cadena de macros para analizar correctamente la entrada del usuario, \NewEnvironse utiliza \env@newenvironmentlo que se hizo \letal \newenvironmentprincipio.

Ahora, \newenvironmentinternamente hace entre otras cosas (un poco simplificado) algo como

\expandafter\def\csname <env-name>\endcsname{<begin-code>}

(Básicamente, hiciste lo correcto sin saber que los componentes internos ya se están ocupando de esto).

Si configura " <env-name>=\csname SOMENAME\endcsname" (lo que resultaría del uso de su macro personalizada \newtheorem{SOMENAME}{}), terminará con un \csname...\endcsnamepar superfluo:

\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...

\expandafter(como probablemente ya sabes) en este caso lo toma \defy lo almacena para mirar hacia el siguiente token y expandirlo primero. Aquí encuentra \csnamelo que busca lo siguiente \endcsnamey expande todo lo que hay entre medio y forma una secuencia de control a partir de eso. Este sería otro \csnameque nuevamente termina correctamente con el final \endcsname. Entonces, realmente aplicas el \csnamemecanismo dos veces a 'ALGÚN NOMBRE' y esto significa que no terminas con \def\SOMENAME{<begin-code>}(como planeaste), sino con

\def\<expansion of \SOMENAME>{<begin-code>}

Si \SOMENAMEestaba definido no teníamos ningún problema:

\documentclass{article}
\usepackage{environ}

\def\SOMENAME{somename}
\NewEnviron{\csname SOMENAME\endcsname}{somename-content: \BODY}

\begin{document}
\begin{somename}
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  Integer feugiat tempus urna, cursus placerat sapien mollis ac.
  Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}

Pero deberíasnodefinirlo; esta interfaz de usuario sería de alguna manera engañosa. Simplemente use \NewEnvironexactamente lo mismo que \newenvironmentcon respecto a la entrada del nombre del entorno:

\documentclass{article}
\usepackage{environ}

\newcommand{\FlorianEnvdefWrapper}[1]{%
  \NewEnviron{#1}[1]{##1: \BODY}
}

\FlorianEnvdefWrapper{somename}

\begin{document}
\begin{somename}{foo-bar}
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  Integer feugiat tempus urna, cursus placerat sapien mollis ac.
  Donec a accumsan orci, in tristique ligula.
\end{somename}
\end{document}

Observación

Cambié el nombre de su macro de ejemplo para evitar conflictos con el amsthmpaquete. Creo que es mejor dejar esas cosas como están, en general. Seguramente hay excepciones, pero perder su funcionalidad por completo puede no ser la mejor opción si puedes evitarlo simplemente eligiendo otro nombre para tu comando.

información relacionada