我正在努力使用 Tikz 进行一些基本计算,并且在为本地范围内的变量分配值时遇到了问题。
考虑以下 MVCE:
\documentclass{article}
\usepackage{ifthen}
\usepackage{tikz}
\newcommand{\mycommand}
{
\def\myvar{0};
\def\myresult{3};
\ifnum\myvar=0
{
\def\myresult{4};
\draw (0,1) node {Test is true!};
}
\fi;
\draw (0,0) node {myresult=\myresult !!!};
}
\begin{document}
\begin{tikzpicture}
\mycommand
\end{tikzpicture}
\end{document}
这样写的话,将会打印“测试为真!”,但是的值myresult
仍为 3。
因此,我假设第二条\def
命令创建了一个新变量,其范围仅限于块if
。经过一番搜索,似乎我可以通过使用以下\global
命令将变量定义为“全局”来解决问题:
\newcommand{\mycommand}
{
\def\myvar{0};
\global\def\myresult{3};
\ifnum\myvar=0
{
\global\def\myresult{4};
\draw (0,1) node {Test is true!};
}
\fi;
\draw (0,0) node {myresult=\myresult !!!};
}
这样,它就可以工作了,尽管我不确定这是否是最佳的(\global
似乎是一个 TeX 命令,并且我已经多次读过在 LaTeX 源中使用低级 TeX 命令是个坏主意......)
但是现在,我的实际代码有点复杂,在“if”块中,它实际上是一个\pgfmathtruncatemacro
。比如说:
\newcommand{\mycommand}
{
\def\myvar{0};
\global\def\myresult{3};
\ifnum\myvar=0
{
\pgfmathtruncatemacro{\myresult}{4}
}
\fi;
\draw (0,0) node {myresult=\myresult !!!};
}
然后我遇到了与上面相同的问题:\pgfmathtruncatemacro
似乎声明了一个新变量,因为我保留该值3
......
并且两者
\global\pgfmathtruncatemacro{\myresult}{4}
或者
\pgfmathtruncatemacro{\global\myresult}{4}
编译失败。
我怎样才能摆脱这个问题?
答案1
这是一种相当安全的“广播”结果的方法,即使得在群组之外使用。
- 在这种情况下,您可以只使用
\xdef
。\xdef
危险吗?嗯,这取决于上下文。如果您注意不要重新定义已知的宏,则不会。\xdef
我不知道是否有人曾经费心提供更万无一失的版本。如有疑问,当然应该检查\@ifdefined
命令是否已定义。如果需要,我可以尝试按照这些思路编写一些东西,但其他人可以做得更好,所以你可能想就此提出一个单独的问题。 - 如果你进行计算,
\pgftruncatemacro
你可以用类似的东西广播结果\pgfmathtruncatemacro{\myresult}{4}\xdef\myresult{\myresult}
- 在某些情况下,例如使用 pgfkeys 时,您不能只使用
\xdef
。在这种情况下,您可以尝试使用\globaldefs
。但是,我强调,除非你绝对确定自己在做什么,否则我不建议这样做。(我曾经在一个答案中使用过它,但当 OP 开始修改它时,它确实引起了问题,所以我非常不愿意走那条路。
这是一个 MWE。
\documentclass{article}
\usepackage{tikz}
\newcommand{\mycommand}
{
\def\myvar{0}
\def\myresult{3}
\ifnum\myvar=0
{
\xdef\myresult{4}
\draw (0,1) node {Test is true!};
}
\fi
\draw (0,0) node {myresult=\myresult !!!};
}
\begin{document}
\begin{tikzpicture}
\mycommand
\end{tikzpicture}
\renewcommand{\mycommand}
{
\def\myvar{0}
\global\def\myresult{3}
\ifnum\myvar=0
{
\pgfmathtruncatemacro{\myresult}{4}
\xdef\myresult{\myresult}
}
\fi
\draw (0,0) node {myresult=\myresult !!!};
}
\begin{tikzpicture}
\mycommand
\end{tikzpicture}
\end{document}
答案2
您的初始代码几乎是正确的。问题是由太多不必要但有害的分列引起的。
请注意,最后的分列仅用于结束 TikZ 命令行。
\documentclass[11pt, border=1cm]{standalone}
\usepackage{ifthen}
\usepackage{tikz}
\newcommand{\mycommand}{%
\def\myvar{0}
\def\myresult{3}
\ifnum\myvar=0 \def\myresult{4}{
\draw (0,1) node {the test is {\color{blue}True}};
}
\fi
{
\draw (0,0) node {and \textit{myresult} is \myresult};
}
}
\begin{document}
\begin{tikzpicture}
\mycommand
\end{tikzpicture}
\end{document}