Tail-recursive, only traditional TeX:
\documentclass{article}
\newcommand\priceloop[1]{\if#1m$\expandafter\priceloop\fi}
\newcommand\price[1]{\expandafter\priceloop\romannumeral\number\number#1 000\relax}
\begin{document}
\price{12}
\end{document}
Tail-recursive, eTeX-extensions:
\documentclass{article}
\newcommand\exchange[2]{#2#1}%
\newcommand\price[1]{\ifnum#1>0 \exchange{$\expandafter\price\expandafter{\the\numexpr#1-1\relax}}\fi}
\begin{document}
\price{12}
\end{document}
Or use one of David Kastrup's \replicate-variants:
\documentclass{article}
\newcommand\gobble[1]{}
\newcommand\xii[2]{\if#2m#1\expandafter\xii\else\expandafter\gobble\fi{#1}}
\newcommand\xiii[2]{\xii{#2}#1\relax}
\newcommand\replicate[1]{\expandafter\xiii\expandafter{\romannumeral\number\number#1 000}}%
\newcommand\price[1]{\replicate{#1}{$}}
\begin{document}
\price{12}
\end{document}
\documentclass{article}
\newcommand\recur[1]{\csname rn#1\recur}
\newcommand\rnm[1]{\endcsname{#1}#1}
\newcommand\rn[1]{}
\newcommand\replicate[1]{\csname rn\expandafter\recur\romannumeral\number\number#1 000\endcsname\endcsname}
\newcommand\price[1]{\replicate{#1}{\$}}
\begin{document}
\price{12}
\end{document}
The sequence \romannumeral\number\number#1 000 instead of just \romannumeral#1000 is for the following reason:
#1 is to be some TeX-⟨number⟩-quantity that is to be multiplied by 1000 by attaching digits 000 so that \romannumeral delivers the corresponding amount of character-tokens m.
#1 is not necessarily a sequence of digits.
It could be a \count-register as well where you need a space-token for separating the number denoting the \count-register from the three zeros to attach to the tokens forming the value held in that \count-register:
Assume you wish to denote the value held in \count-register 17:
\romannumeral\count17000 will not work out because TeX assumes an attempt of denoting the value held in \count-register 17000 and raises an error as there is no \count-register 17000.
\romannumeral\number\number\count17 000 does work out:
The second \number delivers the value that is held in \count-register 17 as digit-sequence. The space behind 17/before 000 is consumed as end-marker of the digit-sequence 17 denoting the \count-register.
The first \number is not needed here/does not change the fact that when the second \number is finished you already have a digit-sequence with three zeros appended which can be processed by \romannumeral.
But the TeX-⟨number⟩-quantity could be a \countdef-token or a \chardef-token or the like as well whereafter a space-token will not be removed by TeX.
Assume someone doing \chardef\sixtyfive=`\A.
\romannumeral\sixtyfive000 will not work out because due to TeX's rules for gathering TeX-⟨number⟩-quantities with \chardef-tokens 000 will not be considered part of the number to be processed by \romannumeral.
But \romannumeral\number\number\sixtyfive⟨space-token⟩000 will work out:
The second \number delivers 65 from the chardef-token \sixtyfive. This 65 is trailed by the ⟨space-token⟩ and the three zeros. The first \number finds the digit-sequence 65 trailed by a ⟨space-token⟩ and eliminates that ⟨space-token⟩. Now \romannumeral as number to convert can gather 65000 and deliver 65 characters m.
\newcommand\price[1]{\iftrue\priceaux#1\fi} \def\priceaux#1\fi{\fi\ifnum#1>0 \$\expandafter\priceaux\expandafter{\numexpr#1-1}\fi}Note the\expandafters are optional. The absorption of\fiby\priceauxmakes it a "tail recursion" – Steven B. Segletes Sep 18 '21 at 01:22\fitrick from an old-timer named...David Carlisle: https://tex.stackexchange.com/questions/372639/trying-to-eliminate-stack-overflow-during-recursion-alphabetic-bubble-sorter/372644#372644 – Steven B. Segletes Sep 18 '21 at 01:30\expandafters "hitting"\numexprhave no effect because\numexpris not expandable.\number, however, is expandable... – Ulrich Diez Sep 19 '21 at 01:30\the\numexpris expandable? If so, then I just need to add\theto my code – Steven B. Segletes Sep 19 '21 at 02:54\numexpris not expandable, even though I know\the\numexprto be expandable. What this means for the code I provided in the earlier comment is that I should have the braced expression as{\the\numexpr#1-1}in order for the\expandafters to have an effect (or, as Ulrich suggested,{\number\numexpr#1-1}). – Steven B. Segletes Sep 19 '21 at 03:06\theand\numberare expandable. Thus you can do\the\numexpr...or\number\numexpr..., just as you like. With\dimexpretc you need to use\the. – Ulrich Diez Sep 19 '21 at 16:26\the\unhbox...all would be well, LOL. – Steven B. Segletes Sep 19 '21 at 16:35\the\numexpris (around 10%) faster than\number\numexpr(there is a difference however between\number\dimexprand\the\dimexpr). – Skillmon Sep 20 '21 at 18:26\numexpron its own isn't expandable, it is more or less the same as using\count, just that it computes the value on the fly based on the input instead of fetching it from a register. – Skillmon Sep 20 '21 at 18:28\numexpr! – Steven B. Segletes Sep 20 '21 at 18:30\theis more like 30% faster. – Skillmon Sep 20 '21 at 18:40