
나는 \pgf@marshal
PGF 패키지 전체에서 분명히 관용적인 사용을 접했는데 왜 그것이 사용되는지 궁금합니다.
예를 들면 다음과 같습니다 pgflibraryshapes.gates.logic.US.code.tex
.
{%
\edef\pgf@marshal{%
\noexpand\pgfpatharc{90}{-90}{\the\pgf@yc}%
}%
\pgf@marshal%
}
이것은 아마도 쉬운 일이지만, 왜 그렇지 않습니까?
\pgfpatharc{90}{-90}{\the\pgf@yc}
?
답변1
\pgfpatharc
사용하지 않지만 ( \pgf@yc
적어도 이미 평가되어 다른 곳에 저장될 때까지는) 사용하는 것이 안전했을 것입니다.
\pgfpatharc{90}{-90}{\pgf@yc}
(짝수 없이 \the
),매뉴얼 자체가 경고한다
주목:PGF는 이러한 레지스터를 사용하여 경로 작업을 수행합니다. 효율성 때문에 경로 명령이 항상 이를 보호하지는 않습니다. 결과적으로 코드는
\pgfpointadd{\pgfpoint{\pgf@xa}{\pgf@ya}}{\pgfpoint{\pgf@xb}{\pgf@yb}}
실패할 수 있음: 내부에서 및
\pgfpointadd
친구\pgf@xa
레지스터가 수정될 수 있습니다. 특히, 평가되기\pgf@xb
전에 변경되는 일이 발생할 수 있습니다.\pgfpoint{\pgf@xb}{\pgf@yb}
올바른 일은 먼저 값을 사용하여 모든 것을 확장\edef
하고 나중에 값을 처리하여 불필요하게 비용이 많이 드는 작업을 수행하는 것입니다. 물론,\pgfpointadd
어떤 레지스터가 사용되는지 확인하기 위해 의 소스 코드를 살펴보는 것만으로 이 문제를 피할 수 있습니다.
(흥미롭게도 주어진 예는 실제로 작동하지만 작동하지 않습니다.
\pgfpointadd{\pgfpoint{\pgf@xb}{\pgf@yb}}{\pgfpoint{\pgf@xa}{\pgf@ya}}
첫 번째 점의 좌표는 저장되고 나중에 두 번째 점의 좌표에 추가되기 때문입니다 \pgf@xa
. \pgf@ya
)
의 경우 \pgfpatharc
, 사용되기 #3
전에 평가를 받고 \pgf@yc
이는 범위에서만 발생하므로 \pgf@yc
이후에도 여전히 동일한 값을 갖습니다 \pgfpatharc
.
그렇습니다. 회로 라이브러리 개발자는 정의를 살펴보고 \pgfpatharc
아무 의미가 없다고 판단했을 수도 있습니다.
그러나 고려해야 할 다른 사항이 있습니다:
\pgfpatharc
회로 라이브러리를 작성할 때 명령이 다르게 작동했을 수도 있습니다 .- 명령 은
\pgfpatharc
나중에 변경될 수 있습니다. - 다른 시점에서 회로 라이브러리의 작성자는 충돌을 발견하고 유사한 매크로 호출을 모두 변경하여 이러한 문제를 다시는 처리할 필요가 없도록 했습니다.
답변2
TeX 실행 모델에 익숙하지 않은 사람들을 위한 또 다른 관점입니다.
위키낱말사전:
마샬(동사)
4. 전송할 데이터를 수집합니다.
5. (컴퓨팅, 전이적) 객체를 나중에 동등한 속성을 가진 객체로 다시 변환할 수 있는 바이트 시퀀스로 표시되는 마샬링된 상태로 직렬화하는 것입니다.
컴퓨팅 맥락에서는 일반적으로 5를 의미하는 것이 바람직하지만 이 경우에는 4를 의미하는 것이 더 관련성이 있는 것으로 보입니다. 그러나 이는 "코드를 토큰 목록으로 직렬화한 다음 나중에 토큰 목록을 코드로 실행"하는 것으로 이해될 수도 있습니다. 하지만 TeX에서는 코드와 토큰 목록이 거의 동일합니다.
tl;dr:
기본적으로 TeX 명령은 "외부에서 내부로" 실행됩니다. 즉, "함수 인수"가 "함수에 전달"되기 전에 "평가"되는 일반적인 프로그램 언어와 달리 TeX에서는 인수가 매크로 그대로.
- Python에서는 그것을 받기 전에 평가되기 때문에 동일
f(1+2)
합니다 . TeX에서는 and 가 동일하지 않습니다.f(3)
1+2
3
f
\f{\numexpr 1+2\relax}
\f{3}
- Python에서는 그것을 받기 전에 평가되기 때문에 동일
이 경우에는 설명된 대로다른 대답, 호출자는 함수에 전달되기 전에 숫자를 조기에 평가하려고 합니다.
TeX에는 토큰을 조작하는 메커니즘이 매우 제한되어 있습니다. 당신이 보는 코드는 다음과 같습니다
eval(r"\pgfpatharc{90}{-90}{" + pgfyc + "}")
Python 구문에서 --- 코드는 토큰 목록으로 조작된 다음 실행됩니다.
\expandafter
대안은 코드의 모든 곳에 추가하는 것인데 이는 확실히 덜 효율적입니다. (도 있지만\expanded{\unexpanded{...}}
코드를 작성할 당시에는 존재하지 않았습니다.)이 관용구가 사용되는 다른 곳은 예를 들어 볼 수 있습니다.사용하는 방법
pgfplots
루프에서 플롯을와 함께\edef\temp{...}\temp
.접두사는
pgf@
매크로 이름이 pgf 패키지 내부에 있음을 나타냅니다. PGF/TikZ 소스 코드를 편집하지 않는 경우 자신만의 이름을 만들어야 하며\pgf@marshal
.