5

In relation with an answer, I see that \foreach does not understand a constant (n) in declare function. Is it a bug? or there is another proper way of code for this situation?

enter image description here

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture} \def\n{7} % number of sides of a heptagon \pgfmathsetmacro{\k}{360/\n} \pgfmathsetmacro{\r}{2} \draw[cyan] (90:\r) foreach \i in {1,...,\n} {--({90+\k*\i}:\r)}--cycle; \end{tikzpicture}

% This does not work! Uncomment this tikzpicture to get a MWE \begin{tikzpicture}[declare function={n=7;r=2;k=360/n;}] \draw (90:r) foreach \i in {1,...,n} {--({90+k*\i}:r)}--cycle; \end{tikzpicture}

% This works, but not natural! Is that a bug of \foreach ? \begin{tikzpicture}[declare function={n=7;r=2;k=360/n;}] \pgfmathsetmacro\m{n} \draw (90:r) foreach \i in {1,...,\m} {--({90+k*\i}:r)}--cycle; \end{tikzpicture}

\end{document}

Black Mild
  • 17,569
  • 2
    I have always found it confusing to use constants in TikZ. I am also very much interested in how declare function constants can be used and what the equivalent pgf set command is. I think \def\n{7} is bad because it can collide with packages - so newcommand is preferred but seem silly for a constant. – hpekristiansen Sep 24 '21 at 02:20
  • 1
    Yes, \newcommand\n{7} is better than \def\n{7}. Both of them can be use in standalone pdf picture that later it can be embbed into LaTeX document via \includegraphics. However, what I think TikZ' syntax should allow \draw (90:r) foreach \i in {1,...,n} {--({90+k*\i}:r)}--cycle; after declare constant/function [declare function={n=7;r=2;k=360/n;}] – Black Mild Sep 24 '21 at 02:36
  • 2
    TikZ runs almost everything through \pgfmathparse, which will recognize n as a math function. Evidently the foreach parser does not. Nor will it recognize (7) or 3+4. – John Kormylo Sep 24 '21 at 05:06
  • 1
    Also, inside an environment (tikzpicture) I would argue that \def is better. It doesn't really matter if it is already defined, as the new definition will be lost when done. OTOH, \gdef and \xdef names should be reserved in the preamble using \newcommand. – John Kormylo Sep 24 '21 at 05:13
  • @JohnKormylo In my code, TikZ/PGF parsers recognizes k and r. So foreach parser seems not as smart as other PGF parsers. It is unbalanced! – Black Mild Sep 24 '21 at 05:22

1 Answers1

7

Since PGF 3.1.2 (I think) you can use the parse=true option of \foreach.

enter image description here

In this situation you have to wrap n in parentheses so that \foreach parses it as a mathematical expression. Without parentheses \foreach will assume that you want an alphabetical loop a,...,n but since the lower limit is not alphabetical it will break.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[declare function={n=7;r=2;k=360/n;}] \draw (90:r) foreach \i [parse=true] in {1,...,(n)} { -- ({90+k*\i}:r) } --cycle; \end{tikzpicture}

\end{document}

Henri Menke
  • 109,596
  • Thank you very much! It works as I expected on TikZ/PGF syntax. I just wonder that * wrapping n in parentheses* is documented in the pgfmanual.pdf or not? – Black Mild Sep 24 '21 at 10:59
  • 2
    @BlackMild It's impossible to document all edge cases. And the manual is more than long enough already. Nobody reads it anyway. – Henri Menke Sep 24 '21 at 20:12
  • At least I know a girl who printed out and read the pgfmanual. She must be in love with TikZ ^^ – Black Mild Jul 28 '22 at 20:56