Herbert has shown how to seperate words by spaces. Here is a very similar solution which prevent deep \ifx ... \fi
nesting (Deep nesting may produce errors when many words is used):
\documentclass{minimal}
\begin{document}
\def\wordsloop#1{\wordsloopiter#1 \nil}
\def\wordsloopiter#1 #2\nil{%
\do{#1} %
\ifx&% #2 is empty, then & equeals &
\let\next\relax
\else
\def\next{\wordsloopiter#2\nil}% iterate
\fi
\next}
\def\do#1{(#1)}
\wordsloop{This is a sentence.}
% we have: (This) (is) (a) (sentence.)
\end{document}
However, it is still very slow if you use many words in the argument.
Loop on tokens can be obtained by similar approch, if you remove the spaces after #1
in the definitions above. But it can be easier:
\documentclass{minimal}
\begin{document}
\def\tokensloop#1{\tokensloopiter#1\nil}
\def\tokensloopiter#1{%
\ifx\nil#1\else\do{#1}\expandafter\tokensloopiter\fi}
\def\do#1{(#1)}
\tokensloop{aa bb}
% we have (a)(a)(b)(b)
\end{document}
You can also use \toksloop
command from etextools
package directly.
Note that spaces are ignored.
For spaces, catcode or other tricks may be used to read the characters verbatimly. That is more complex.
For example, we can use \obeyspaces
to change the catcode of spaces:
\documentclass{minimal}
\begin{document}
\def\charsloop{\begingroup\obeyspaces\charsloophelper}
\def\charsloophelper#1{\charsloopiter#1\nil\endgroup}
\def\charsloopiter#1{%
\ifx\nil#1\else\do{#1}\expandafter\charsloopiter\fi}
\def\do#1{(#1)}
\charsloop{aa bb}
% we have (a)(a)( )( )(b)(b)
\end{document}
(Newlines are still ignored with \obeyspaces
only.)