1

Why does the following code not work ?

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

I have seen examples of the use of \csname SOMENAME\endcsname for macro with no arguments but I do not know how to do it with a \NewEnviron or a \newcommand having multiple arguments. I am prompted with the error ! Missing \endcsname inserted.

  • Could you give us a complete example? – cfr Jul 30 '15 at 0:57
  • As @cfr already stated: You don't need the \csname ...\endcsname stuff for defining an new environment name, regardless whether this is done with \NewEnviron, newenvironment, \NewDocumentEnvironment etc. – user31729 Jul 30 '15 at 5:58
  • What's the purpose of redefining \newtheorem? – egreg Jul 30 '15 at 9:50
3

You don't want a command name for the name of an environment. Just the name is fine.

So, you can do this:

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

Note that this code doesn't require amsthm, you could just use \newcommand\newtheorem... unless you need the package for other reasons.

Also, you don't ever do anything with the second argument, even though you create the command so that it is required. In the above example, nothing is ever done with oaks.

I'm not convinced this is really what you want to do. The output from the above code is:

trees and leaves and things

As Christian Hupfer points out, this will, of course, break anything which uses \newtheorem in the standard sense. As egreg says, it is not at all obvious what purpose redefining \newtheorem like this serves. It seems almost guaranteed to make for trouble sooner or later... probably sooner.

  • 2
    Perhaps you should note, that this \renewcommand of \newtheorem could break other documents using \newtheorem in the 'correct' way. In my opinion, this should be declared \@onlypreamble too. – user31729 Jul 30 '15 at 6:01
  • 1
    @ChristianHupfer Indeed. I really don't understand the point of doing this: just seems to be asking for trouble. But I suspect that the OP is actually trying to do something different since it makes no sense to feed \newtheorem 2 arguments and only ever use 1 of them. – cfr Jul 30 '15 at 12:59
  • Yes, the purpose is quite unclear – user31729 Jul 30 '15 at 13:17
3

Why does the following code not work?

Let's have a closer look at what \NewEnviron does:

After a short macro chain to parse user input properly \NewEnviron uses \env@newenvironment which was \let to \newenvironment in the beginning.

Now, \newenvironment internally does among other things (a little simplified) something like

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

(Basically you did the right thing without knowing that the internals are taking care of this alredy.)

If you set "<env-name>=\csname SOMENAME\endcsname" -- that would result from using your custom macro like \newtheorem{SOMENAME}{} -- you end up with a superfluous \csname...\endcsname pair:

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

\expandafter (as you probabilly know) in this case grabs \def and stores it to look ahead to the next token and expands this first. Here, it finds \csname which looks for the next \endcsname and expands everything in between and forms a control sequence out of that. This would be another \csname that is again correctly terminated by the trailing \endcsname. So, you really apply the \csname mechanism twice to 'SOMENAME' and this means that you don't end up with \def\SOMENAME{<begin-code>} (as you planed to), but with

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

If \SOMENAME was defined we had no 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}

But you should not define it; this user interface would be somehow misleading. Just use \NewEnviron exactly as \newenvironment concerning the input of the environments name:

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

Remark

I changed the name of your example macro to avoid clashes with the amsthm package. I think it is better to keep those things as they are, in general. Surely there are exceptions, but losing its functionality completely may not be the best option if you can avoid it by simply chosing another name for you command.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.