3

While I was answering another question, I found the error

! Illegal unit of measure (pt inserted).

only when I use ... in a \foreach with a simple operation of the list length:

\documentclass{article}
\usepackage{tikz}
\usepackage{listofitems}
\setsepchar{;}

\begin{document}

\readlist\points{(1,2); (2,3); (3,2); (1,1); (2,2)}

This works: \begin{tikzpicture} \foreach \i in {1,2,3,4} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

This works: \begin{tikzpicture} \foreach \i in {1,...,4} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

This works: \begin{tikzpicture} \foreach \i in {1,2,3,\pointslen-1} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

This gives the error \texttt{! Illegal unit of measure (pt inserted).} \begin{tikzpicture} \foreach \i in {1,...,\pointslen-1} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture} \end{document}

CarLaTeX
  • 62,716

2 Answers2

5

Not sure where the actual problem is (though my guess is in the \foreach limits evaluator), but enclosing the suspect term in \numexpr...\relax (to evaluate an integer) fixes it.

\documentclass{article}
\usepackage{tikz}
\usepackage{listofitems}
\setsepchar{;}

\begin{document}

\readlist\points{(1,2); (2,3); (3,2); (1,1); (2,2)}

This works: \begin{tikzpicture} \foreach \i in {1,2,3,4} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

This works: \begin{tikzpicture} \foreach \i in {1,...,4} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

This works: \begin{tikzpicture} \foreach \i in {1,2,3,\pointslen-1} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture}

%This gives the error %\texttt{! Illegal unit of measure (pt inserted).} \begin{tikzpicture} \foreach \i in {1,...,\numexpr\pointslen-1\relax} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture} \end{document}

enter image description here

  • Thank you, Steven! I wait a bit before accepting to see if someone knows the exact reason. – CarLaTeX Nov 06 '21 at 19:05
  • @CarLaTeX The current behavior reminds me of this question: https://tex.stackexchange.com/questions/519113/strange-foreachevaluate-behavior. Maybe related...(or not) – Steven B. Segletes Nov 06 '21 at 19:09
  • @CarLaTeX To show it has nothing to do with listofitems, one gets the same error result with the syntax: \def\tmp{5} \begin{tikzpicture} \foreach \i in {1,...,\tmp-1} {\draw \points[\i] -- \points[\i+1];} \end{tikzpicture} – Steven B. Segletes Nov 06 '21 at 19:16
  • Thanks, I leave out the listofitems tag. – CarLaTeX Nov 06 '21 at 19:17
  • I tried with int(...) even with an evaluate but I didn't manage to solve the problem as you did. – CarLaTeX Nov 06 '21 at 19:19
5

The last item in the specification of the range for \foreach has to be an integer. Also

\foreach \i in {1,...,5-1} {...}

would fail with the same error. To the contrary, \numexpr\pointslen-1\relax will work.

An expl3 implementation:

\documentclass{article}
\usepackage{tikz}
\usepackage{xfp}

\ExplSyntaxOn \NewDocumentCommand{\definelist}{mm} { \seq_clear_new:c { l_carlatex_list_#1_seq } \seq_set_split:cnn { l_carlatex_list_#1_seq } { ; } { #2 } } \cs_generate_variant:Nn \seq_set_split:Nnn { c }

\NewExpandableDocumentCommand{\getlistitem}{mm} { \seq_item:cn { l_carlatex_list_#1_seq } { #2 } } \NewExpandableDocumentCommand{\getlistlen}{m} { \seq_count:c { l_carlatex_list_#1_seq } } \ExplSyntaxOff

\begin{document} \definelist{points}{(1,2); (2,3); (3,2); (1,1); (2,2)}

This works: \begin{tikzpicture} \foreach \i in {1,...,\inteval{\getlistlen{points}-1}} { \draw \getlistitem{points}{\i} -- \getlistitem{points}{\i+1}; } \end{tikzpicture}

\end{document}

enter image description here

egreg
  • 1,121,712