3

I'm looking for a macro that takes in input a general term of a sequence and write the sequence extensively.

What I mean is a command \GenSeq{general term}{index}{min index}{max index} so that for example

\GenSeq{f(i)}{i}{1}{n} produces

enter image description here

\GenSeq{f(i)}{i}{k}{n} produces

enter image description here

\GenSeq{\theta^{(s)}}{s}{s}{T}

enter image description here

I wonder whether such a thing can be programmed in latex

1
  • could be done although the syntax \GenSeq{\theta^{(#1)}}{s}{T} would be easier if you'd allow that, to save finding the parameter in the template "by hand" just use the built in parameter mechanism. – David Carlisle Nov 12 '20 at 14:19
5

enter image description here

\documentclass{article}

\def\GenSeq#1#2#3{%
\def\zz##1{#1}%
\def\zzstart{#2}%
\zz{#2},
\ifx\zzstart\zzzero\zz{1}\else\ifx\zzstart\zzone\zz{2}\else\zz{#2+1}\fi\fi,
\ldots,\zz{#3}}
\def\zzzero{0}
\def\zzone{1}
\begin{document}

\parskip\bigskipamount

$\GenSeq{f(#1)}{1}{n}$

$\GenSeq{f(#1)}{k}{n}$

$\GenSeq{\theta^{(#1)}}{s}{T}$

\end{document}
4
  • Alright, I've upvoted by I have absolutely not the faintest idea how this is possibly working... – campa Nov 12 '20 at 15:10
  • @campa Hint: If \GenSeq's 1st argument is the sequence f(#1), then \def\zz##1{#1} from within \GenSeq's definition text expands to \def\zz#1{f(#1)}. (#1 from \GenSeq's definition text is replaced by the tokens that are passed as first argument, i.e., is replaced by the tokens f(#1) and ##1 from \GenSeq's definition text is reduced to #1). – Ulrich Diez Nov 12 '20 at 17:25
  • @UlrichDiez Erm... I fear you are grossly overestimating my intellect... – campa Nov 12 '20 at 19:53
  • 1
    @campa it is doing \newcommand\zz[1]{f(#1)} \zz{1}, \z{2},\ldots,\zz{n} with a test for the start of the list being 0 or 1 in which case the second item uses 1 or 2 rather than appending +1 – David Carlisle Nov 12 '20 at 19:55
3

An implementation with expl3.

The first mandatory argument to \GenSeq is a template, with #1 standing for the current index in the “loop“. The second argument is the start point, the third argument is the end point.

If the second argument is an integer (recognized via a regular expression, zero or one hyphen/minus sign and one or more digits), the second printed item will have the index computed, otherwise it will be <start point>+1. However

  1. if the start point and end point coincide, just one item will be printed;
  2. if the start point is numeric and the end point is numeric as well and differs by one or two, only the relevant items will be printed;
  3. otherwise, the starting item, the next, dots and the ending item will be printed.

With \GenSeq*, dots will be added at the end to indicate an infinite sequence.

\documentclass{article}
\usepackage{amsmath}
%\usepackage{xparse} % not needed with LaTeX 2020-10-01 or later

\ExplSyntaxOn

\NewDocumentCommand{\GenSeq}{smmm}
 {% #1 = optional *
  % #2 = template
  % #3 = starting point
  % #4 = end point
  \pinkcollins_genseq:nnn { #2 } { #3 } { #4 }
  \IfBooleanT{#1}{,\dotsc}
 }

\cs_new_protected:Nn \pinkcollins_genseq:nnn
 {
  % turn the template into a (temporary) function
  \cs_set:Nn \__pinkcollins_genseq_temp:n { #1 }
  % do the main work
  \tl_if_eq:nnTF { #2 } { #3 } 
   {% if #2=#3, not much to do
    \__pinkcollins_genseq_temp:n { #2 }
   }
   {% now the hard work
    \__pinkcollins_genseq_do:nn { #2 } { #3 }
   }
 }

\cs_new_protected:Nn \__pinkcollins_genseq_do:nn
 {% #1 = start point, #2 = end point
  % first check whether #1 is an integer
  % \-? = one optional minus sign
  % [[:digit:]]+ = one or more digits
  % \Z = up to the end of the input
  \regex_match:nnTF { \-? [[:digit:]]+ \Z } { #1 }
   {
    \__pinkcollins_genseq_number:nn { #1 } { #2 }
   }
   {
    \__pinkcollins_genseq_symbolic:nn { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \__pinkcollins_genseq_number:nn
 {% #1 = start point, #2 = end point
  \tl_if_eq:enTF { \int_eval:n { #1 + 1 } } { #2 }
   {
    \__pinkcollins_genseq_temp:n { #1 },\__pinkcollins_genseq_temp:n { #2 }
   }
   {
    \__pinkcollins_genseq_temp:n { #1 },
    \__pinkcollins_genseq_temp:n { \int_eval:n { #1+1 } },
    \tl_if_eq:enF { \int_eval:n { #1 + 2 } } { #2 } { \dots, }
    \__pinkcollins_genseq_temp:n { #2 }
   }
 }
\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { e } { T, F, TF }

\cs_new_protected:Nn \__pinkcollins_genseq_symbolic:nn
 {% #1 = start point, #2 = end point
  \__pinkcollins_genseq_temp:n { #1 },
  \__pinkcollins_genseq_temp:n { #1+1 },
  \dots,
  \__pinkcollins_genseq_temp:n { #2 }
 }

\ExplSyntaxOff

\begin{document}

$\GenSeq{f(#1)}{1}{n}$

$\GenSeq{f(#1)}{0}{n}$

$\GenSeq{f(#1)}{1}{1}$

$\GenSeq{f(#1)}{1}{2}$

$\GenSeq{f(#1)}{1}{3}$

$\GenSeq{f(#1)}{1}{4}$

$\GenSeq{f(#1)}{-2}{k}$

$\GenSeq{f(#1)}{k}{n}$

$\GenSeq*{\theta^{(#1)}}{s}{T}$

\end{document}

enter image description here


A different usage of the *-variant could be to make the sequence descending:

\documentclass{article}
\usepackage{amsmath}
%\usepackage{xparse} % not needed with LaTeX 2020-10-01 or later

\ExplSyntaxOn

\NewDocumentCommand{\GenSeq}{smmm}
 {% #1 = optional * for reverse sequence
  % #2 = template
  % #3 = starting point
  % #4 = end point
  \IfBooleanTF{#1}
   {
    \cs_set:Nn \__pinkcollins_genseq_sign: { - }
   }
   {
    \cs_set:Nn \__pinkcollins_genseq_sign: { + }
   }
  \pinkcollins_genseq:nnn { #2 } { #3 } { #4 }
 }

\cs_new_protected:Nn \pinkcollins_genseq:nnn
 {
  % turn the template into a (temporary) function
  \cs_set:Nn \__pinkcollins_genseq_temp:n { #1 }
  % do the main work
  \tl_if_eq:nnTF { #2 } { #3 } 
   {% if #2=#3, not much to do
    \__pinkcollins_genseq_temp:n { #2 }
   }
   {% now the hard work
    \__pinkcollins_genseq_do:nn { #2 } { #3 }
   }
 }

\cs_new_protected:Nn \__pinkcollins_genseq_do:nn
 {% #1 = start point, #2 = end point
  % first check whether #1 is an integer
  % \-? = one optional minus sign
  % [[:digit:]]+ = one or more digits
  % \Z = up to the end of the input
  \regex_match:nnTF { \-? [[:digit:]]+ \Z } { #1 }
   {
    \__pinkcollins_genseq_number:nn { #1 } { #2 }
   }
   {
    \__pinkcollins_genseq_symbolic:nn { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \__pinkcollins_genseq_number:nn
 {% #1 = start point, #2 = end point
  \tl_if_eq:enTF { \int_eval:n { #1 \__pinkcollins_genseq_sign: 1 } } { #2 }
   {
    \__pinkcollins_genseq_temp:n { #1 },\__pinkcollins_genseq_temp:n { #2 }
   }
   {
    \__pinkcollins_genseq_temp:n { #1 },
    \__pinkcollins_genseq_temp:n { \int_eval:n { #1\__pinkcollins_genseq_sign: 1 } },
    \tl_if_eq:enF { \int_eval:n { #1 \__pinkcollins_genseq_sign: 2 } } { #2 } { \dots, }
    \__pinkcollins_genseq_temp:n { #2 }
   }
 }
\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { e } { T, F, TF }

\cs_new_protected:Nn \__pinkcollins_genseq_symbolic:nn
 {% #1 = start point, #2 = end point
  \__pinkcollins_genseq_temp:n { #1 },
  \__pinkcollins_genseq_temp:n { #1\__pinkcollins_genseq_sign:1 },
  \dots,
  \__pinkcollins_genseq_temp:n { #2 }
 }

\ExplSyntaxOff

\begin{document}

\textbf{Ascending}

$\GenSeq{f(#1)}{1}{n}$

$\GenSeq{f(#1)}{0}{n}$

$\GenSeq{f(#1)}{1}{1}$

$\GenSeq{f(#1)}{1}{2}$

$\GenSeq{f(#1)}{1}{3}$

$\GenSeq{f(#1)}{1}{4}$

$\GenSeq{f(#1)}{-2}{k}$

$\GenSeq{f(#1)}{k}{n}$

$\GenSeq{\theta^{(#1)}}{s}{T}$

\textbf{Descending}

$\GenSeq*{f(#1)}{n}{1}$

$\GenSeq*{f(#1)}{n}{0}$

$\GenSeq*{f(#1)}{1}{1}$

$\GenSeq*{f(#1)}{2}{1}$

$\GenSeq*{f(#1)}{3}{1}$

$\GenSeq*{f(#1)}{4}{1}$

$\GenSeq*{f(#1)}{k}{-2}$

$\GenSeq*{f(#1)}{k}{n}$

$\GenSeq*{\theta^{(#1)}}{s}{T}$

\end{document}

enter image description here

2

For the sake of having fun playing around with expl3 I wanted to do it with expl3.

But I ended up doing it with a mixture of expl3 and my own code:

  • I use expl3-regex-code for checking if ⟨min index⟩—⁠(!)⁠ ⁠without expanding tokens of ⟨min index⟩⁠ ⁠(!)⁠—forms a sequence of at most one sign and some decimal digits and—if so—for incrementing and passing on to the replacement-routine the (incremented) value of ⟨min index⟩.
  • I use my own code for replacing ⟨index⟩ within ⟨general term⟩.

⟨min index⟩ is not expanded for checking if it denotes/yields (only) a valid TeX-⟨number⟩-quantity. I reject the idea of such a check/test for the following reason: No testing-method for checking whether fully expanding ⟨min index⟩ yields only a valid TeX-⟨number⟩-quantity is known to me which is not flawed in some way and/or which imposes no restrictions on possible user-input. When attempting to implement an algorithm for such a test, then you are facing the halting-problem: At the time of expanding them, the tokens forming ⟨min index⟩ may form an arbitrary expansion-based algorithm. Having an algorithm check whether such an algorithm in the end yields a valid TeX-⟨number⟩-quantity implies having an algorithm check whether an other arbitrary algorithm terminates at all/terminates without error-messages. This is the halting-problem. Alan Turing proved in 1936 that it is not possible to implement an algorithm which for any arbitrary algorithm can "decide" whether that algorithm will ever terminate.

In the beginning I intended to do the replacing of ⟨index⟩ by means of expl3-routines also:

Part VII - The l3tl package - Token lists, section 3 Modifying token list variables of interface3.pdf (Released 2020-10-27) states:

\tl_replace_all:Nnn ⟨tl var⟩ {⟨old tokens⟩} {⟨new tokens⟩}

Replaces all occurrences of ⟨old tokens⟩ in the ⟨tl var⟩ with ⟨new tokens⟩. ⟨Old tokens⟩ cannot contain {, } or # (more precisely, explicit character tokens with category code 1 (begin-group) or 2 (end-group), and tokens with category code 6). As this function operates from left to right, the pattern ⟨old tokens⟩ may remain after the replacement (see \tl_remove_all:Nn for an example).

(You are told that category code 1 is "begin-group" and that category code 2 is "end-group". I wonder why you are not told that category code 6 is "parameter". ;-) )

I tried doing it with \tl_replace_all:Nnn.

But this failed because the statement is not true.

(You can test yourself:

In the example below not all occurrences of u get replaced by d:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_set:Nn \l_tmpa_tl {uu{uu}uu{uu}}
\tl_replace_all:Nnn \l_tmpa_tl {u} {d}
\tl_show:N \l_tmpa_tl
\stop

⟨old tokens⟩ is u.
⟨new tokens⟩ is d.
All restrictions for ⟨old tokens⟩ and ⟨new tokens⟩ are obeyed.

Console output is:

\l_tmpa_tl=dd{uu}dd{uu}.

It seems that only occurrences not nested between a pair of matching explicit character tokens with category code 1 (begin-group) respective 2 (end-group) are replaced.

So the statement of all occurrences being replaced is wrong.

If the statement was correct, then console output would be:

\l_tmpa_tl=dd{dd}dd{dd}.

)

So I decided to write my own replacement-routine \ReplaceAllIndexOcurrences from scratch, without expl3.

As a side-effect \ReplaceAllIndexOcurrences does replace all explicit character tokens of category code 1 by {1 and all explicit character tokens of category code 2 by }2.

\documentclass[landscape, a4paper]{article}

%===================[adjust margins/layout for the example]====================
\csname @ifundefined\endcsname{pagewidth}{}{\pagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pdfpagewidth}{}{\pdfpagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pageheight}{}{\pageheight=\paperheight}%
\csname @ifundefined\endcsname{pdfpageheight}{}{\pdfpageheight=\paperheight}%
\textwidth=\paperwidth
\oddsidemargin=1.5cm
\marginparsep=.2\oddsidemargin
\marginparwidth=\oddsidemargin
\advance\marginparwidth-2\marginparsep
\advance\textwidth-2\oddsidemargin
\advance\oddsidemargin-1in
\evensidemargin=\oddsidemargin
\textheight=\paperheight
\topmargin=1.5cm
\footskip=.5\topmargin
{\normalfont\global\advance\footskip.5\ht\strutbox}%
\advance\textheight-2\topmargin
\advance\topmargin-1in
\headheight=0ex
\headsep=0ex
\pagestyle{plain}
\parindent=0ex
\parskip=0ex 
\topsep=0ex
\partopsep=0ex
%==================[eof margin-adjustments]====================================

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\GenSeq{mmmm}{
  \group_begin:
  % #1 = general term
  % #2 = index
  % #3 = min index
  % #4 = max index
  \regex_match:nnTF { ^[\+\-]?\d+$ }{ #3 }{
    \int_step_inline:nnnn {#3}{1}{#3+1}{\ReplaceAllIndexOcurrences{#1}{#2}{##1},}
  }{
   \ReplaceAllIndexOcurrences{#1}{#2}{#3},
   \ReplaceAllIndexOcurrences{#1}{#2}{#3+1},
  }
  \ldots,
  \ReplaceAllIndexOcurrences{#1}{#2}{#4}
  \group_end:
}
\ExplSyntaxOff

\makeatletter
%%//////////////////// Code of my own replacement-routine: ////////////////////
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo,
%%    \UD@PassFirstToSecond, \UD@Exchange, \UD@removespace
%%    \UD@CheckWhetherNull, \UD@CheckWhetherBrace,
%%    \UD@CheckWhetherLeadingTokens, \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@removespace{}\UD@firstoftwo{\def\UD@removespace}{} {}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\z@\UD@secondoftwo}%
  {\expandafter\z@\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
  \romannumeral\expandafter\UD@secondoftwo\expandafter{\expandafter{%
  \string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\z@\UD@firstoftwo}%
  {\expandafter\z@\UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's leading tokens form a specific 
%% token-sequence that does neither contain explicit character tokens of 
%% category code 1 or 2 nor contain tokens of category code 6:
%%.............................................................................
%% \UD@CheckWhetherLeadingTokens{<argument which is to be checked>}%
%%                              {<a <token sequence> without explicit 
%%                                character tokens of category code
%%                                1 or 2 and without tokens of
%%                                category code 6>}%
%%                              {<internal token-check-macro>}%
%%                              {<tokens to be delivered in case
%%                                <argument which is to be checked> has
%%                                <token sequence> as leading tokens>}%
%%                              {<tokens to be delivered in case 
%%                                <argument which is to be checked>
%%                                does not have <token sequence> as
%%                                leading tokens>}%
\newcommand\UD@CheckWhetherLeadingTokens[3]{%
  \romannumeral\UD@CheckWhetherNull{#1}{\expandafter\z@\UD@secondoftwo}{%
    \expandafter\UD@secondoftwo\string{\expandafter
    \UD@@CheckWhetherLeadingTokens#3{\relax}#1#2}{}}%
}%
\newcommand\UD@@CheckWhetherLeadingTokens[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter\z@\expandafter\expandafter
   \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% \UD@internaltokencheckdefiner{<internal token-check-macro>}%
%%                              {<token sequence>}%
%% Defines <internal token-check-macro> to snap everything 
%% until reaching <token sequence>-sequence and spit that out
%% nested in braces.
%%-----------------------------------------------------------------------------
\newcommand\UD@internaltokencheckdefiner[2]{%
  \@ifdefinable#1{\long\def#1##1#2{{##1}}}%
}%
\UD@internaltokencheckdefiner{\UD@InternalExplicitSpaceCheckMacro}{ }%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%
%%   \romannumeral\UD@ExtractFirstArgLoop{ABCDE\UD@SelDOm} yields  {A}
%%
%%   \romannumeral\UD@ExtractFirstArgLoop{{AB}CDE\UD@SelDOm} yields  {AB}
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  {\z@#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% \ReplaceAllIndexOcurrences{<term with <index>>}
%%                           {<index>}%
%%                           {<replacement for<index>>}%
%%
%% Replaces all <index> in <term with <index>> by <replacement for<index>>
%%
%% !!! Does also replace all pairs of matching explicit character tokens of
%%     catcode 1/2 by matching braces!!!
%% !!! <index> must not contain explicit character tokens of catcode 1 or 2 !!!
%% !!! <index> must not contain tokens of catcode 6 !!!
%% !!! Defines temporary macro \UD@temp, therefore not expandable !!!
%%-----------------------------------------------------------------------------
\newcommand\ReplaceAllIndexOcurrences[2]{%
  % #1 - <term with <index>>
  % #2 - <index>
  \begingroup
  \UD@internaltokencheckdefiner{\UD@temp}{#2}%
  \expandafter\endgroup
  \romannumeral\UD@ReplaceAllIndexOcurrencesLoop{#1}{}{#2}%
}%
\newcommand\UD@ReplaceAllIndexOcurrencesLoop[4]{%
  % Do:
  %  \UD@internaltokencheckdefiner{\UD@temp}{<index>}%
  %  \romannumeral\UD@ReplaceAllIndexOcurrencesLoop
  %                                 {<term with <index>>}%
  %                                 {<sequence created so far, initially empty>}%
  %                                 {<index>}%
  %                                 {<replacement for<index>>}%
  %
  % #1 - <term with <index>>
  % #2 - <sequence created so far, initially empty>
  % #3 - <index>
  % #4 - <replacement for<index>>
  \UD@CheckWhetherNull{#1}{\z@#2}{%
    \UD@CheckWhetherLeadingTokens{#1}{#3}{\UD@temp}{%
      \expandafter\expandafter\expandafter\UD@ReplaceAllIndexOcurrencesLoop
      \expandafter\expandafter\expandafter{%
        \expandafter\UD@firstoftwo\expandafter{\expandafter}\UD@temp#1%
      }{#2#4}%
    }{%
      \UD@CheckWhetherLeadingTokens{#1}{ }{\UD@InternalExplicitSpaceCheckMacro}{%
         \expandafter\UD@ReplaceAllIndexOcurrencesLoop
         \expandafter{\UD@removespace#1}{#2 }%
      }{%
        \UD@CheckWhetherBrace{#1}{%
          \expandafter\expandafter\expandafter\UD@PassFirstToSecond
          \expandafter\expandafter\expandafter{%
          \expandafter\UD@PassFirstToSecond\expandafter{%
            \romannumeral\expandafter\UD@ReplaceAllIndexOcurrencesLoop
              \romannumeral\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{}{#3}{#4}%
          }{#2}}%
          {\expandafter\UD@ReplaceAllIndexOcurrencesLoop\expandafter{\UD@firstoftwo{}#1}}%
        }{%
          \expandafter\UD@PassFirstToSecond\expandafter{%
            \romannumeral\expandafter\UD@Exchange\romannumeral\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{\z@#2}%
          }{\expandafter\UD@ReplaceAllIndexOcurrencesLoop\expandafter{\UD@firstoftwo{}#1}}%
        }%
      }%
    }%
    {#3}{#4}%
  }%
}%
\makeatother
%%=============================================================================
%%///////////////// End of code of my own replacement-routine. ////////////////

\makeatletter
\newcommand\ParenthesesIfMoreThanOneUndelimitedArgument[1]{%
  \begingroup
  \protected@edef\UD@temp{#1}%
  \expandafter\expandafter\expandafter\UD@CheckWhetherNull
  \expandafter\expandafter\expandafter{\expandafter\UD@firstoftwo\UD@temp{}.}{%
    \endgroup#1%
  }{%
    \expandafter\UD@CheckWhetherNull
    \expandafter{\romannumeral\expandafter\expandafter
                              \expandafter            \expandafter
                              \expandafter\expandafter
                              \expandafter            \z@
                              \expandafter\expandafter
                              \expandafter            \UD@firstoftwo
                              \expandafter\UD@firstoftwo
                              \expandafter{%
                              \expandafter}%
                              \UD@temp{}.}{%
      \endgroup#1%
    }{%
      \endgroup(#1)%
    }%
  }%
}%
\makeatother

\begin{document}

Let's use \verb|i| as \textit{$\langle$index$\rangle$}---\verb|$\GenSeq{f(i)}{i}{1}{n}$| yields:

$\GenSeq{f(i)}{i}{1}{n}$

\vfill

Let's use \verb|i| as \textit{$\langle$index$\rangle$}, but \textit{$\langle$min~index$\rangle$} not a digit  sequence---\verb|$\GenSeq{f(i)}{i}{k}{n}$| yields:

$\GenSeq{f(i)}{i}{k}{n}$

\vfill

Let's use \verb|s| as \textit{$\langle$index$\rangle$}---\verb|$\GenSeq{\theta^{(s)}}{s}{s}{T}$| yields:

$\GenSeq{\theta^{(s)}}{s}{s}{T}$

\vfill

Let's use \verb|\Weird\Woozles| as \textit{$\langle$index$\rangle$}---\begin{verbatim}
$\GenSeq{%
          \sqrt{%
            \vphantom{(}%
            ParenthesesIfMoreThanOneUndelimitedArgument{\Weird\Woozles}\cdot\ParenthesesIfMoreThanOneUndelimitedArgument{\Weird\Woozles}%
            \vphantom{)}%
          }%
        }%
        {\Weird\Woozles}%
        {s}%
        {T}$
\end{verbatim} yields:

$\GenSeq{%
          \sqrt{%
            \vphantom{(}%
            \ParenthesesIfMoreThanOneUndelimitedArgument{\Weird\Woozles}\cdot\ParenthesesIfMoreThanOneUndelimitedArgument{\Weird\Woozles}%
            \vphantom{)}%
          }%
        }%
        {\Weird\Woozles}%
        {s}%
        {T}$

\vfill

Let's use the explicit space token as \textit{$\langle$index$\rangle$}---\verb|$\GenSeq{f( )}{ }{k}{n}$| yields:

$\GenSeq{f( )}{ }{k}{n}$

\vfill

Let's use the explicit space token as \textit{$\langle$index$\rangle$}---\verb|$\GenSeq{f( )}{ }{-5}{n}$| yields:

$\GenSeq{f( )}{ }{-5}{n}$

\vfill\vfill

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.