複数の引数を持つマクロの定義と\csnameの使用

複数の引数を持つマクロの定義と\csnameの使用

次のコードが動作しないのはなぜですか?

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

引数なしの for マクロの使用例は見たことがありますが、複数の引数を持つまたは\csname SOMENAME\endcsnameでそれを実行する方法がわかりません。エラー が表示されます。\NewEnviron\newcommand! 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...他の理由でパッケージが必要でない限り、 を使用することもできます。

また、必須となるようにコマンドを作成したとしても、2 番目の引数については何も行いません。上記の例では、 については何も行われません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。つまり、実際にはメカニズムを 'SOMENAME' に 2 回適用し、 (計画どおりに)では\csnameなく、次のようになります。\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。一般的には、そのままにしておく方が良いと思います。もちろん例外もありますが、コマンドに別の名前を選択するだけで回避できる場合、機能を完全に失うことは最善の選択肢ではないかもしれません。

関連情報