0

Is there a way to write a user-defined Latex command that takes no arguments and returns the nth string from a repository of strings?

baseball,marble,coin,watermelon,beachball

Johnny threw a \myWord{1}, \myWord{3}, and a \myWord{4} to Joe.

My aim would be to have this return:

Johnny threw a baseball, coin, and a watermelon to Joe.

(Perhaps a random word would be thrown in for no argument, as with \myWord{}).

Sigur
  • 37,330

2 Answers2

2

With the help of expl3 (loaded by xparse):

\documentclass[]{article}

\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_ignoramus_words_seq
\int_new:N \l_ignoramus_count_int
\NewDocumentCommand \setwordlist { m }
  {
    \seq_set_from_clist:Nn \l_ignoramus_words_seq { #1 }
    \int_set:Nn \l_ignoramus_count_int { \seq_count:N \l_ignoramus_words_seq }
  }
\NewDocumentCommand \myword { o }
  {
    \seq_item:Nn \l_ignoramus_words_seq
      {
        \IfNoValueTF { #1 }
          { \int_rand:n { \l_ignoramus_count_int } }
          { #1 }
      }
  }
\ExplSyntaxOff

\setwordlist{baseball,marble,coin,watermelon,beachball}

\begin{document}
Johnny threw a \myword, \myword, and a \myword\ to Joe.

Johnny threw a \myword[1], \myword[3], and a \myword[4] to Joe.
\end{document}

enter image description here

Skillmon
  • 60,462
1

You can use etoolbox to process a list:

enter image description here

\documentclass{article}

\usepackage{etoolbox,xfp}

\newcounter{wordcnt}
\newcommand{\setwordlist}[1]{%
  \setcounter{wordcnt}{0}% Reset word counter
  \renewcommand{\do}[1]{% With every element in word list, ...
    \stepcounter{wordcnt}% ... step word counter ...
    \expandafter\def\csname wordlist\thewordcnt\endcsname{##1}% ... and store word.
  }%
  \docsvlist{#1}% Process word list
}

\newcommand{\myWord}[1]{%
  % https://tex.stackexchange.com/q/53068/5764
  \if\relax\detokenize{#1}\relax
    \csname wordlist\fpeval{randint(1,\value{wordcnt})}\endcsname
  \else
    \csname wordlist#1\endcsname
  \fi
}

\begin{document}

\setwordlist{baseball,marble,coin,watermelon,beachball}

Johnny threw a \myWord{1}, \myWord{3}, and a \myWord{4} to Joe.

Johnny threw a \myWord{1}, \myWord{}, and a \myWord{4} to Joe.

\end{document}

Note that the random selection uses xfp and does not consider any form of selection without replacement. As such, duplicates may be drawn.

Werner
  • 603,163