具有多個參數的巨集的定義和 \csname 的用法

具有多個參數的巨集的定義和 \csname 的用法

為什麼下面的程式碼不起作用?

\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套件發生衝突。我認為一般來說,最好保持這些東西原樣。當然也有例外,但如果您可以透過簡單地為命令選擇另一個名稱來避免它,那麼完全失去其功能可能不是最好的選擇。

相關內容