다음 코드가 작동하지 않는 이유는 무엇입니까?
\Requirepackage{amsthm}
\renewcommand\newtheorem[2]{%
\NewEnviron{\csname #1\endcsname}[1]{%
##1 : \BODY
}
}
인수 없이 for 매크로를 사용하는 예를 본 적이 있지만 a 또는 여러 인수가 있는 \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}
이 코드는 필요하지 않습니다.amsthm\newcommand\newtheorem...
, 다른 이유로 패키지가 필요한 경우가 아니면 그냥 사용할 수 있습니다 .
또한 필수 명령을 생성하더라도 두 번째 인수로는 아무 작업도 수행하지 않습니다. 위의 예에서는 oaks
.
나는 이것이 정말로 당신이 원하는 것인지 확신하지 못합니다. 위 코드의 출력은 다음과 같습니다.
처럼크리스티앙 후퍼(Christian Hupfer)는 다음과 같이 지적합니다., 이것은 물론 \newtheorem
표준적인 의미에서 사용하는 모든 것을 깨뜨릴 것입니다. 처럼egreg 라고\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'에 메커니즘을 두 번 적용하면 (계획한 대로) \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
. 그런 것들은 대체로 그대로 두는 게 낫다고 생각해요. 물론 예외도 있지만, 단순히 명령에 다른 이름을 선택하여 이를 피할 수 있다면 기능을 완전히 잃는 것은 최선의 선택이 아닐 수도 있습니다.