宏中的合法“局部变量”(参数)命令引发“未定义的控制序列”?

宏中的合法“局部变量”(参数)命令引发“未定义的控制序列”?

考虑一下这个MWE:

\documentclass[varwidth,tightpage,border=1bp]{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\makeatletter
\gdef\getMyInfoString{%
  \let\trfm\relax % ! Undefined control sequence.
  \pgfgettransform{\trfm}% with previous commented: ! Undefined control sequence. <argument> \trfm
  \edef\tout{%
    pgfgettransform: \trfm ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
  }
  \tout % output tout
}
\makeatother

\pgfgettransform{\trfmX}%
\makeatletter
\typeout{Manually check: %
    pgfgettransform: \trfmX ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
}
\makeatother

\typeout{This is via macro function: \getMyInfoString}%

\end{tikzpicture}
\end{document}

如果你编译它,首先\typeout会将以下内容打印到标准输出:

Manually: pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt}; pgf@pt@aa, pgf@p
t@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 0.0, 0.0, 1.0

...而第二个\typeout引发了一个错误:

! Undefined control sequence.
\getMyInfoString ->\let \trfm 
                              \relax \pgfgettransform {\trfm }\edef \tout {p...
l.30 \typeout{This is: \getMyInfoString}
                                        %
? 

显然,latex想要执行控制\trfm序列/命令/标记/宏 - 虽然我打算将其作为一个“局部变量”,但它将用作“参数” \pgfgettransform(然后用数据填充它)。

有没有办法“保护”这个\trfm宏 - 以便\getMyInfoString正确执行,并在调用时返回一个字符串(我猜是以可扩展的方式,因为意图是在中使用它\typeout)?

答案1

如果要获取日志文件中的当前转换数据,只需执行 之前的命令即可\typeout

\documentclass{article}

\usepackage{tikz}

\makeatletter
\def\getMyInfoString{%
  \pgfgettransform{\trfm}%
  \edef\tout{%
    \space\space pgfgettransform: \trfm ;^^J%
    \space\space pgf@pt@aa: \pgf@pt@aa;^^J%
    \space\space pgf@pt@ba: \pgf@pt@ba;^^J%
    \space\space pgf@pt@ab: \pgf@pt@ab;^^J%
    \space\space pgf@pt@bb: \pgf@pt@bb
  }%
  \typeout{Here's the current transform:^^J\tout} % output tout
}
\makeatother

\begin{document}
\begin{tikzpicture}
\getMyInfoString
\end{tikzpicture}
\end{document}

日志文件中的输出是

Here's the current transform:
  pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt};
  pgf@pt@aa: 1.0;
  pgf@pt@ba: 0.0;
  pgf@pt@ab: 0.0;
  pgf@pt@bb: 1.0

您不能在 中执行赋值\typeout;定义就是赋值。

答案2

怎么样:

\documentclass{scrartcl}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfgettransformentries{ \a }{\b }{ \c }{ \d }{ \sx }{ \sy }
\typeout{a=\a, b=\b, c=\c, d=\d, sx=\sx, sy=\sy}
\end{tikzpicture}
\end{document}

哪个会产生a=1.0, b=0.0, c=0.0, d=1.0, sx=0.0pt, sy=0.0pt并避免令人讨厌的普通 TeX 黑客?

编辑:好的,看了你的评论后,我明白你又陷入了什么命令在什么时候被展开的困境。看来 typeout 在这里相当糟糕。不幸的是,我无法给你一些\expandafter解决这种情况的魔法,但一个简单的解决方法是将设置变量和产生输出分开,例如

\documentclass{scrartcl}
\usepackage{tikz}
\newcommand\setVars{\pgfgettransformentries{\a}{\b}{\c}{\d}{\sx}{\sy}}
\newcommand\printVars{a=\a, b=\b, c=\c, d=\d, sx=\sx, sy=\sy}
\begin{document}
\setVars\typeout{\printVars}
\end{document}

答案3

我会将其作为答案发布,因为它确实有一定的帮助 - 如果崩溃的“本地选项”宏是预先“预定义”的\gdef(这里只是相关的代码片段):

\makeatletter
\gdef\tout{}\gdef\trfm{} % ** this
\gdef\getMyInfoString{%
  \let\trfm\relax % ! Undefined control sequence.
  \pgfgettransform{\trfm}% with previous commented: ! Undefined control sequence. <argument> \trfm
  \edef\tout{%
    pgfgettransform: \trfm ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
  }
  \tout % output tout
}
\makeatother

...然后 MWE 似乎通过了,没有编译错误;并且它打印出:

Manually check: pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt}; pgf@pt@aa,
 pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 0.0, 0.0, 1.0
This is via macro function: \let \relax \edef {{1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0p
t}} \edef {pgfgettransform: ; pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 
0.0, 0.0, 1.0} 

显然,通过宏打印出来的结果并不完全符合预期 - 这就是为什么最好有一个正确的答案;但至少在这种情况下,所需的信息泄漏到标准输出 - 这对我来说已经足够了:)

相关内容