PGF에서 \pgf@marshal의 관용적 사용

PGF에서 \pgf@marshal의 관용적 사용

나는 \pgf@marshalPGF 패키지 전체에서 분명히 관용적인 사용을 접했는데 왜 그것이 사용되는지 궁금합니다.

예를 들면 다음과 같습니다 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+23f\f{\numexpr 1+2\relax}\f{3}
  • 이 경우에는 설명된 대로다른 대답, 호출자는 함수에 전달되기 전에 숫자를 조기에 평가하려고 합니다.

  • TeX에는 토큰을 조작하는 메커니즘이 매우 제한되어 있습니다. 당신이 보는 코드는 다음과 같습니다

    eval(r"\pgfpatharc{90}{-90}{" + pgfyc + "}")
    

    Python 구문에서 --- 코드는 토큰 목록으로 조작된 다음 실행됩니다.

    \expandafter대안은 코드의 모든 곳에 추가하는 것인데 이는 확실히 덜 효율적입니다. (도 있지만 \expanded{\unexpanded{...}}코드를 작성할 당시에는 존재하지 않았습니다.)

  • 이 관용구가 사용되는 다른 곳은 예를 들어 볼 수 있습니다.사용하는 방법pgfplots루프에서 플롯을와 함께 \edef\temp{...}\temp.

  • 접두사는 pgf@매크로 이름이 pgf 패키지 내부에 있음을 나타냅니다. PGF/TikZ 소스 코드를 편집하지 않는 경우 자신만의 이름을 만들어야 하며 \pgf@marshal.

관련 정보