3

I am having some problems with macro expansion in TikZ nodes. The MWE below is supposed to draw nodes at specified coordinates and display their coordinate rounded to the nearest number, but it shows the coordinates of the last node for both of them.

\documentclass[]{article}

\usepackage{pgfplots}
\usepackage{xparse}

\ExplSyntaxOn

\tl_new:N \x
\tl_new:N \x_round

\NewDocumentCommand \mynode { m } {
    \tl_set:Nn \x { 
        \fp_eval:n { #1 } 
    }

    \tl_set:Nn \x_round { 
       \fp_eval:n { round ( \x ) } 
    }

    \addplot [style={mark=none}] coordinates { ( \x , \x ) } node { \x_round } ;
}

\ExplSyntaxOff

\begin{document}
    \begin{tikzpicture}
        \begin{axis}            
            \mynode{1.1}
            \mynode{2.2}
        \end{axis}
    \end{tikzpicture}
\end{document}

I assume the problem is that the \x_round is not expanded in the node until the end of the environments. How can I ensure \x_round is expanded immediately?

I have noticed that replacing the command with

\NewDocumentCommand \mynode { m } {
    \addplot [style={mark=none}] coordinates { ( #1 , #1 ) } node { \fp_eval:n { round ( #1 ) }  } ;
}

does fix the problem, but for my real code, it is inadequate as the code is more complex.

  • 2
    \x is a blasphemy regarding expl3 naming convention ;-) – user31729 Feb 4 at 9:29
  • Hehe, I wanted to keep it simple for the MWE. My actual code as proper naming ;) – slo Feb 4 at 10:52
1

You should use \tl_set:Nx, but it's quite pointless anyway:

\documentclass{article}

\usepackage{pgfplots}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \mynode { m }
 {
  \addplot [style={mark=none}]
    coordinates { ( \fp_eval:n { #1 } , \fp_eval:n { #1 } ) }
    node { \fp_eval:n { round(#1) } } ;
 }

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
  \begin{axis}
    \mynode{1.1}
    \mynode{2.2}
  \end{axis}
\end{tikzpicture}

\end{document}

Avoid names such as \x and \x_round, use the proper naming conventions.

enter image description here

You can use variables (here I use fp ones, but tl can be good as well, provided you set them with \tl_set:Nx). However, text in the node has to be expanded before passing it to PGF:

\documentclass{article}

\usepackage{pgfplots}
\usepackage{xparse}

\ExplSyntaxOn

\fp_new:N \l_slo_coord_x_fp
\fp_new:N \l_slo_coord_x_round_fp

\NewDocumentCommand \mynode { m }
 {
  \fp_set:Nn \l_slo_coord_x_fp { #1 }
  \fp_set:Nn \l_slo_coord_x_round_fp { round ( \l_slo_coord_x_fp ) }
  \use:x
   {
    \exp_not:N \addplot [style={mark=none}]
      coordinates { ( \fp_use:N \l_slo_coord_x_fp , \fp_use:N \l_slo_coord_x_fp ) }
      node { \fp_use:N \l_slo_coord_x_round_fp } ;
   }
 }

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
  \begin{axis}
    \mynode{1.1}
    \mynode{2.2}
  \end{axis}
\end{tikzpicture}

\end{document}
  • Perhaps worth using an auxiliary? I'd tend to avoid evaluating the same expression multiple times, both for efficiency and as it could have a random component. – Joseph Wright Feb 4 at 9:47
  • @JosephWright It doesn't really work here, because one has to expand the argument to node. – egreg Feb 4 at 9:55
  • Thanks, it works great. I actually tried using \tl_set:Nx, but I guess node has to be unexpanded if I understand things correctly, right? – slo Feb 4 at 11:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.