Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix infinite loop in the example on Loops over list of items provided under Section 2.6.2 of TeX-programming-notes.tex #485

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/latex/pgfplots/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2024-07-10 Hanson Char <[email protected]> and plante <[email protected]>

Fix infinite loop in the example on Loops over list of items provided
under Section 2.6.2 of TeX-programming-notes.tex

2021-12-27 Christian Feuersaenger <[email protected]>

fix linux file read permissions of some new lua files in TDS zip
Expand Down
10 changes: 5 additions & 5 deletions doc/latex/pgfplots/TeX-programming-notes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ \subsubsection{Loops over list of items}
Looping over a list of items is very similar, only we will need |\ifx| in place of |\ifnum| and we need some end marker instead of the threshold value. However, how do we specify the list itself? Let's make some comma-separated list, e.\,g. |{a,b,c,d}| and call the end marker |\listingloopENDMARKER|.

\begin{codeexample}[]
\def\listingloopENDMARKER{\par \listingloopENDMARKER}
\def\listingloopENDMARKER{\listingloopENDMARKER}
\long\def\listingloop#1in#2#3{%
\looppicker{#1}{#3}#2,\listingloopENDMARKER,%
}%
Expand All @@ -933,18 +933,18 @@ \subsubsection{Loops over list of items}
#2%
\def\next{\looppicker{#1}{#2}}%
\fi
\next
\next%
Copy link
Author

@hansonchar hansonchar Jul 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note I needed to append % here so make notes won't get into an infinite loop. Basically a hack to get around what seems to be a flaw of the existing build system.

}%
\listingloop\x in{a,b,c,,d,e}{%
The current item is `\x'
\listingloop\x in{aa, b,c ,,d,e}{%
Copy link
Author

@hansonchar hansonchar Jul 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified the test cases to have a wider range of coverage of what otherwise could have gone wrong without being noticed.

The current item is `\x'\par
}
\end{codeexample}

Again, we make clear the subtleties contained therein:
\begin{itemize}
\item We have defined |\listingloopENDMARKER| to replace itself. This is possible because |\ifx| will only compare first-level expansion, see Section~\ref{sec:branching}.
\item We seem to miss a white space in \ldots|#1in#2|\ldots. However, tokens are always ending with an additional white space as |\xin| is not equal to |\x in|. Hence, none is needed here and more than one white space would probably get gobbled.
\item The definition |\looppicker#1#2#3,|\ldots has three arguments but the recursive call |\looppicker{#1}{#2}| only gives two arguments!? This is the actual magic making this type of list possible! \TeX{} is actually scanning beyond the scope of the given token to obtain the third argument. In effect, we are biting off piece by piece, list item by list item off the given list. All because we have stated an additional |,| -- comma being the item separator -- in the definition of the |\looppicker| macro. The expansion of the loop macro will always pick up one more item from the list concatenated to its end until it has reached the |\ENDMARKER|. This is added to the list's very end on the loop's start, and there it stops.
\item The definition |\looppicker#1#2#3,|\ldots has three arguments but the recursive call |\looppicker{#1}{#2}| only gives two arguments!? This is the actual magic making this type of list possible! \TeX{} is actually scanning beyond the scope of the given token to obtain the third argument. In effect, we are biting off piece by piece, list item by list item off the given list. All because we have stated an additional |,| -- comma being the item separator -- in the definition of the |\looppicker| macro. The expansion of the loop macro will always pick up one more item from the list concatenated to its end until it has reached the |\listingloopENDMARKER|. This is added to the list's very end on the loop's start, and there it stops.
\end{itemize}

\subsection{More On \TeX}
Expand Down