Definição de uma macro com múltiplos argumentos e uso de \csname

Definição de uma macro com múltiplos argumentos e uso de \csname

Por que o código a seguir não funciona?

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

Já vi exemplos do uso de \csname SOMENAME\endcsnamemacro for sem argumentos mas não sei como fazer com a \NewEnvironou \newcommandcom múltiplos argumentos. Eu sou avisado com o erro ! Missing \endcsname inserted.

Responder1

Você não quer um nome de comando para o nome de um ambiente. Apenas o nome está bom.

Então, você pode fazer isso:

\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}

Observe que este código não requeramsthm, você pode usar apenas \newcommand\newtheorem...a menos que precise do pacote por outros motivos.

Além disso, você nunca faz nada com o segundo argumento, mesmo que crie o comando para que seja necessário. No exemplo acima, nada é feito com oaks.

Não estou convencido de que isso seja realmente o que você deseja fazer. A saída do código acima é:

árvores e folhas e coisas

ComoChristian Hupfer destaca, isso irá, é claro, quebrar qualquer coisa que seja usada \newtheoremno sentido padrão. Comoegreg diz, não é de todo óbvio a que propósito \newtheoremserve uma redefinição como esta. Parece quase garantido que haverá problemas mais cedo ou mais tarde... provavelmente mais cedo.

Responder2

Por que o código a seguir não funciona?

Vamos dar uma olhada mais de perto no que \NewEnvironfaz:

Após uma curta cadeia de macros para analisar corretamente a entrada do usuário, \NewEnvironusa-se \env@newenvironmento que era \letno \newenvironmentinício.

Agora, \newenvironmentinternamente faz entre outras coisas (um pouco simplificado) algo como

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

(Basicamente você fez a coisa certa sem saber que os internos já estão cuidando disso.)

Se você definir " <env-name>=\csname SOMENAME\endcsname" - isso resultaria do uso de sua macro personalizada como \newtheorem{SOMENAME}{}- você acabaria com um \csname...\endcsnamepar supérfluo:

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

\expandafter(como você provavelmente sabe), neste caso, pega \defe armazena-o para antecipar o próximo token e expande-o primeiro. Aqui, ele descobre \csnamequem procura o próximo \endcsnamee expande tudo o que está no meio e forma uma sequência de controle a partir disso. Este seria outro \csnameque seria novamente encerrado corretamente pelo \endcsname. Então, você realmente aplica o \csnamemecanismo duas vezes a 'SOMENAME' e isso significa que você não termina com \def\SOMENAME{<begin-code>}(como planejou), mas com

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

Se \SOMENAMEfoi definido não tivemos 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}

Mas voce devianãoDefina isso; esta interface de usuário seria de alguma forma enganosa. Basta usar \NewEnvironexatamente como \newenvironmentna entrada do nome do ambiente:

\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}

Observação

Alterei o nome da sua macro de exemplo para evitar conflitos com o amsthmpacote. Acho que é melhor manter essas coisas como estão, em geral. Certamente há exceções, mas perder completamente sua funcionalidade pode não ser a melhor opção se você puder evitá-lo simplesmente escolhendo outro nome para seu comando.

informação relacionada