為什麼下面的程式碼不起作用?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
我見過使用\csname SOMENAME\endcsname
不帶參數的 for 巨集的範例,但我不知道如何使用 a\NewEnviron
或\newcommand
具有多個參數的 a 來執行此操作。我收到錯誤提示! Missing \endcsname inserted
。
答案1
您不需要環境名稱的命令名稱。只要名字就好。
所以,你可以這樣做:
\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}
請注意,此程式碼不需要阿姆斯特姆\newcommand\newtheorem...
,除非您因其他原因需要該軟體包,否則您可以直接使用。
另外,即使您建立了需要它的命令,您也不會對第二個參數執行任何操作。在上面的例子中,什麼也沒做oaks
。
我不相信這真的是你想要做的。上述程式碼的輸出為:
作為克里斯蒂安·赫弗指出,這當然會破壞任何\newtheorem
在標準意義上使用的東西。作為艾格格 說\newtheorem
,這樣重新定義的目的是什麼,根本不明顯。看起來幾乎肯定遲早會惹上麻煩……也許更早。
答案2
為什麼下面的程式碼不起作用?
讓我們仔細看看它的\NewEnviron
作用:
經過一段簡短的宏鏈來正確解析使用者輸入後,就開始\NewEnviron
使用\env@newenvironment
它了。\let
\newenvironment
現在,\newenvironment
除了其他事情(稍微簡化)之外,內部還做了類似的事情
\expandafter\def\csname <env-name>\endcsname{<begin-code>}
(基本上你做了正確的事情,而不知道內部已經在處理這個問題了。)
如果你設定「<env-name>=\csname SOMENAME\endcsname
」——這將是由於使用你的自訂巨集而導致的\newtheorem{SOMENAME}{}
——你最終會得到一對多餘的\csname...\endcsname
:
\expandafter\def\csname\csname SOMENAME\endcsname\endcsname...
\expandafter
(正如您可能知道的那樣)在這種情況下,抓取\def
並儲存它以展望下一個標記並首先擴展它。在這裡,它會找出\csname
下一個\endcsname
並擴展其間的所有內容,並從中形成一個控制序列。這將是另一個\csname
由尾隨正確終止的\endcsname
。因此,您實際上\csname
對“SOMENAME”應用了兩次該機制,這意味著您最終不會得到\def\SOMENAME{<begin-code>}
(如您計劃的那樣),而是得到
\def\<expansion of \SOMENAME>{<begin-code>}
如果\SOMENAME
定義了我們就沒有問題:
\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}
但你應該不是定義它;這個使用者介面會在某種程度上產生誤導。只需按照環境名稱的輸入\NewEnviron
完全相同的方式使用即可:\newenvironment
\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}
評論
我更改了範例巨集的名稱以避免與amsthm
套件發生衝突。我認為一般來說,最好保持這些東西原樣。當然也有例外,但如果您可以透過簡單地為命令選擇另一個名稱來避免它,那麼完全失去其功能可能不是最好的選擇。