如何让这个 TikZ 图片更加符合地道?(环境图)

如何让这个 TikZ 图片更加符合地道?(环境图)

我正在重新排版《计算机程序的结构和解释》中的一张图(图3.9):

原始图像

我对 TikZ 的思考结果如下:

TikZ 图像

请忽略白色主色调,我想让图片在深色和浅色背景下均可使用。

这是图片的代码:

#+name: remark-environments-3-9
#+header: :imagemagick yes :iminoptions -density 300 :imoutoptions -geometry 800
#+header: :fit yes :headers '("\\usepackage{tikz} \\usetikzlibrary{positioning,fit,petri,arrows}")
#+header: :buffer on
#+begin_src latex :results raw file :exports both :file figure-3-9.png
\begin{tikzpicture}[inner sep=0mm,>=stealth',very thick,color=black!50]
\begin{scope} [node distance=4mm]
\node (make withdraw) {make-withdraw: ...};
\node (fake1) [right=of make withdraw,xshift=40mm] {};
\node (W1) [below=of make withdraw.west,anchor=west] {W1:};
\end{scope}

\node (g env) [draw,rectangle,inner sep=2mm, fit=(make withdraw) (W1) (fake1)]
{ };

\node (g env name) [left={of g env},text width=1cm]
{global env} edge[->,very thick] (g env);

\begin{scope}[node distance=0mm]
\node [draw,minimum size=5mm,circle,tokens=1,below=of W1.east, yshift=-20mm] (w1fun-left) {};
\node [draw,minimum size=5mm,circle,tokens=1,right=of w1fun-left, xshift=0mm]
(w1fun-right) {};

\node [rectangle, fit=(w1fun-left) (w1fun-right)] (w1fun)
{} edge [<-, to path={|- (\tikztotarget)}] (W1.east);
\end{scope}

\node [below=of w1fun-left, align=left] {parameters: amount \\ body:...}
edge [<-] (w1fun-left.center); 


\node (E1-env) [below=of g env,yshift=5mm,draw,inner sep=2mm] {balance: amount}
edge [->] (g env);
\node [left=of E1-env,xshift=5mm] {E1} edge [->] (E1-env);

\path (w1fun-right.center) edge[->,to path={-| (\tikztotarget)}] (E1-env.south);

\end{tikzpicture}


#+end_src

这看起来或多或少与原始代码相匹配,甚至看起来更好,但我想知道有哪些最明显(和不太明显)的方法可以使代码更符合惯用方式。

我尤其不喜欢:

  1. “两点”范围
  2. “代币”仍然是黑色的,因此不可见
  3. 手动 xshift 和 yshift
  4. 如果我想制作更大的环境图,我需要定义一些宏或类似的东西以供以后使用,以制作类似 \environment 或 \closure 的东西。
  5. 还有其他方法可以让它看起来更好吗?

答案1

至于你的观点:

  1. 您可以将此范围设为pic。这也解决了第 4 点。
  2. 您可以使用colored tokens={black!50}
  3. 如果在定位语法中添加距离,则不需要手动移位,例如right=44mm of make withdraw
  4. 重复事物的一个非常方便的方法是使用pics。当你用手指指向它时:指向形状的箭头就是pins。另一个显而易见的事情是使用样式。我box为绘制的重复矩形添加了样式。可以向这些样式添加参数,以及在没有设置参数时应用的默认值。在示例中,box参数是inner sep,其默认值是2mm
  5. 当不清楚目标输出是什么时,很难让事情变得更好。暂时我添加了font=\sffamily

这是一个完整的示例,它还使用该backgrounds库来添加黑色背景。如果你在第 5 点下进一步解释你的期望,我会很乐意重申。

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{positioning,arrows,fit,petri,backgrounds}
\begin{document}
\begin{tikzpicture}[inner sep=0mm,>=stealth',very thick,color=black!50,
    background rectangle/.style={fill=black},show background rectangle,
    font=\sffamily,pics/two dots/.style={code={
     \node [draw,minimum size=5mm,circle,colored tokens={black!50}] 
     (#1-left) {};
    \node [draw,minimum size=5mm,circle,colored tokens={black!50},
    right=0pt of #1-left]
        (#1-right) {};
    \node [rectangle, fit=(#1-left) (#1-right)] (#1){};
    }},
    every pin edge/.style={<-,very thick},
    box/.style={draw,rectangle,inner sep=#1},box/.default=2mm]
  % 
  \node (make withdraw) {make-withdraw: \dots};
  \node (fake1) [right=44mm of make withdraw] {};
  \node (W1) [below=4mm of make withdraw.west,anchor=west] {W1:};
  %
  \node (g env) [box, fit=(make withdraw) (W1) (fake1),
  pin={[text width=1cm,pin distance=10mm]left:global env}]
  { };
  %
  \path ([yshift=-20mm]W1.east)pic{two dots=w1fun}
    (w1fun) edge [<-, to path={|- (\tikztotarget)}] (W1.east);
  %
  \node [below=of w1fun-left, align=left] {parameters: amount \\ body: \dots}
    edge [<-] (w1fun-left.center); 
  \node (E1-env) [below=5mm of g env,box,
    pin={[pin distance=5mm]left:E1}] {balance: amount}
    edge [->] (g env);
  \path (w1fun-right.center) edge[->,to path={-| (\tikztotarget)}] 
    (E1-env.south);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容