Definition eines Makros mit mehreren Argumenten und Verwendung von \csname

Definition eines Makros mit mehreren Argumenten und Verwendung von \csname

Warum funktioniert der folgende Code nicht?

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

Ich habe Beispiele für die Verwendung eines Makros ohne Argumente gesehen \csname SOMENAME\endcsname, weiß aber nicht, wie ich es mit einem \NewEnvironoder einem \newcommandmit mehreren Argumenten machen soll. Ich erhalte die Fehlermeldung ! Missing \endcsname inserted.

Antwort1

Sie möchten keinen Befehlsnamen für den Namen einer Umgebung. Nur der Name ist ausreichend.

Sie können also Folgendes tun:

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

Beachten Sie, dass dieser Code nicht erfordertamstham, Sie können es einfach verwenden, \newcommand\newtheorem...es sei denn, Sie benötigen das Paket aus anderen Gründen.

Außerdem tun Sie mit dem zweiten Argument nie etwas, obwohl Sie den Befehl so erstellen, dass er erforderlich ist. Im obigen Beispiel wird mit nie etwas getan oaks.

Ich bin nicht überzeugt, dass das wirklich das ist, was Sie tun möchten. Die Ausgabe des obigen Codes lautet:

Bäume und Blätter und Dinge

AlsChristian Hupfer weist darauf hin, dies wird natürlich alles zerstören, was \newtheoremim Standardsinn verwendet wird. Alsegreg sagt, es ist überhaupt nicht klar, welchem ​​Zweck \newtheoremeine solche Neudefinition dient. Es scheint fast garantiert, dass es früher oder später zu Problemen führen wird ... wahrscheinlich früher.

Antwort2

Warum funktioniert der folgende Code nicht?

Schauen wir uns genauer an, was das \NewEnvironbedeutet:

Danach wird eine kurze Makrokette \NewEnvironverwendet , um die Benutzereingaben richtig zu analysieren \env@newenvironment, was am Anfang der Fall \letwar .\newenvironment

Nun \newenvironmentmacht intern unter anderem (etwas vereinfacht) so etwas wie

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

(Im Grunde haben Sie das Richtige getan, ohne zu wissen, dass die internen Prozesse sich bereits darum kümmern.)

Wenn Sie " " setzen <env-name>=\csname SOMENAME\endcsname– was sich aus der Verwendung Ihres benutzerdefinierten Makros wie folgt ergeben würde \newtheorem{SOMENAME}{}– erhalten Sie ein überflüssiges \csname...\endcsnamePaar:

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

\expandafter(wie Sie wahrscheinlich wissen) greift \defund speichert es in diesem Fall, um nach dem nächsten Token zu suchen und dieses zuerst zu erweitern. Hier findet es \csnamewhich, sucht nach dem nächsten \endcsnameund erweitert alles dazwischen und bildet daraus eine Kontrollsequenz. Dies wäre eine weitere \csname, die wieder korrekt durch das abschließende beendet wird \endcsname. Sie wenden den Mechanismus also tatsächlich zweimal auf 'SOMENAME' an und das bedeutet, dass Sie nicht (wie geplant) \csnamemit enden , sondern mit\def\SOMENAME{<begin-code>}

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

Wenn \SOMENAMEdefiniert war, hatten wir kein Problem:

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

Aber du solltestnichtdefinieren; diese Benutzeroberfläche wäre irgendwie irreführend. Verwenden Sie einfach \NewEnvirongenau das gleiche wie \newenvironmentbei der Eingabe des Umgebungsnamens:

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

Anmerkung

Ich habe den Namen Ihres Beispielmakros geändert, um Konflikte mit dem amsthmPaket zu vermeiden. Ich denke, es ist im Allgemeinen besser, diese Dinge so zu belassen, wie sie sind. Sicherlich gibt es Ausnahmen, aber der vollständige Verlust der Funktionalität ist möglicherweise nicht die beste Option, wenn Sie dies vermeiden können, indem Sie einfach einen anderen Namen für Ihren Befehl wählen.

verwandte Informationen