1

I looked here and tried to use
\expandonce{\pgfmathprint{\n+1}} \expandonce{\&} Text inside the matrixcontent-loop.

But this does not work. What do I have to do?

\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usepackage{etoolbox}

\begin{document} \begin{tikzpicture}[ declare function={ f(\n)=0.5*\n; }, ] \let\mymatrixcontent\empty \foreach \n in {1,...,8}{%% \xappto\mymatrixcontent{ %\expandonce{\pgfmathprint{f(\n)}} \expandonce{&} works not %\expandonce{\pgfmathprint{\n+1}} \expandonce{&} works not too \expandonce{\pgfmathprint{1+1}} \expandonce{&} works } \gappto\mymatrixcontent{\} }%%

\matrixmatrix of nodes, ampersand replacement=&{ \mymatrixcontent }; \end{tikzpicture} \end{document}

cis
  • 8,073
  • 1
  • 16
  • 45

2 Answers2

4

The \expandonce macro only expands what's directly in front of it, here \pgfmathprint, and only once at that. It will certainly not expand \n which is what you want here. I'd suggest

\xappto\mymatrixcontent{\noexpand\pgfmathprint{f(\n)}}
\gappto\mymatrixcontent{\&\\}

protecting \pgfmathprint from expansion. There's no need to expand \&, this is only defined properly inside \matrix. Or even

\gappto\mymatrixcontent{\pgfmathprint}
\xappto\mymatrixcontent{{f(\n)}}% double braces!
\gappto\mymatrixcontent{\&\\}

Or just

\xappto\mymatrixcontent{%
  \noexpand\pgfmathprint{f(\n)}\noexpand\&\noexpand\\}%

I'll also provide two different approaches

  1. by using an ungrouped loop via the .list handler and PGFkeys own “appto” (in the form of the .append key handler) and
  2. by using matrix' own row counter \pgfmatrixcurrentrow which we can use inside PGFMath.

The first alternative solution uses \foreach internally, so you can use any \foreach compatible list (like {1,...,8,10,17,35.5}). Since we use a style we can automatically set the matrix' content without having to specify it again.

The second alternative is probably not the easiest in this case but isn't that powerless either. Though, for more complex tables, the package might be worth to invest in.

Code

\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usepackage{etoolbox}
\begin{document}

% 0. using \foreach and etoolbox \begin{tikzpicture}[declare function={f(\n)=0.5*\n;}] \def\mymatrixcontent{$x$&$f(x)$\} \foreach \n in {1,...,8}{ \xappto\mymatrixcontent{ \noexpand\pgfmathprint{\n} \noexpand& \noexpand\pgfmathprint{f(\n)}\noexpand\}} \matrix[matrix of nodes, ampersand replacement=&] (m) {\mymatrixcontent}; \end{tikzpicture}

% 1. using .list and PGFkeys (w/o etoolbox) \begin{tikzpicture}[declare function={f(\n)=0.5*\n;}, row builder/.style={ /mymatrixcontent/.initial=$x$&$f(x)$\, @row builder/.list={#1}, node contents=\pgfkeysvalueof{/mymatrixcontent}}, @row builder/.style={ /mymatrixcontent/.append=#1 & \pgfmathprint{f(#1)} \}] \matrix (m) [ matrix of nodes, ampersand replacement=&, row builder={1,...,8}]; \end{tikzpicture}

% 2. using row counter \begin{tikzpicture}[declare function={f(\n)=0.5*\n;}] \matrix[ matrix of nodes, ampersand replacement=&, nodes in empty cells, column 1/.append style={nodes={node contents=\pgfmathprint{int(\pgfmatrixcurrentrow-1)}}}, column 2/.append style={nodes={node contents=\pgfmathprint{f(\pgfmatrixcurrentrow-1)}}}, row 1 column 1/.style={nodes={node contents=$x$}}, row 1 column 2/.style={nodes={node contents=$f(x)$}} ] (m) { & \ & \ & \ & \ & \ & \ & \ & \ & \}; \end{tikzpicture} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
3

You want to expand just \n, so something like

\xappto\mymatrixcontent{%
  \noexpand\pgfmathprint{\n} \noexpand\&
  \noexpand\pgfmathprint{f(\n)} \noexpand\&
  \noexpand\pgfmathprint{\n+1} \noexpand\\
}

Under standard settings \noexpand\& might be just \&, but \noexpand doesn't hurt and would be necessary if \& somehow gets a different definition.

You can do it in different ways.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}

\ExplSyntaxOn

\NewDocumentCommand{\intstep}{O{1}mm} { \int_step_inline:nnn { #1 } { #2 } { #3 } }

% emulation of etoolbox \appto \ProvideDocumentCommand{\appto}{mm} { \tl_put_right:Nn #1 { #2 } }

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}[declare function={f(\n)=0.5*\n;}] \def\mymatrixcontent{} \intstep{8}{ \appto\mymatrixcontent{\pgfmathprint{#1} & \pgfmathprint{f(#1)} & \pgfmathprint{#1+1} \} } \matrixmatrix of nodes, ampersand replacement=&{ \mymatrixcontent }; \end{tikzpicture}

$\tikzset{declare function={f(\n)=0.5*\n;}} \begin{array}{ccc} \intstep{8}{\pgfmathprint{#1} & \pgfmathprint{f(#1)} & \pgfmathprint{#1+1} \} \end{array}$

\end{document}

The \intstep command takes as optional argument the starting point (default 1), then two mandatory arguments, namely the upper bound and a template for what to do, where the current index is denoted by #1.

For the TikZ matrix, the indirection of first populating a scratch token list variable seems needed. Not so for a simpler array approach.

enter image description here

egreg
  • 1,121,712