Получите отпечатанный вывод макроса обратно в качестве текста замены для другого макроса.

Получите отпечатанный вывод макроса обратно в качестве текста замены для другого макроса.

Предположим, у вас есть рекурсивный макрос TeX \formula(с внутренними управляющими последовательностями, перемещающими локальные счетчики), который после расширения и набора выводит выражение, которое удовлетворяет всем вашим потребностям: например, выражение типа f(x) (в выводе dvi).

Как получить эту набранную формулу обратно в виде строки символов, которую можно использовать в качестве замены «дословного» текста другого макроса, например \def\secondformula{f(x)}?

Вот в качестве МВЭ определение формулы, определяющей через рекурсию функцию Бесселя первого рода любого порядка

\newcount\BesselOrder
\newcount\BesselOrderMinusOne

\def\BesselZERO{besj0(x)}
\def\BesselONE{besj1(x)}

\def\Recursion{%
\advance\BesselOrder by -1
\advance\BesselOrderMinusOne by -1
((2 * \the\BesselOrder / x) * {\BesselJ{\the\BesselOrder}} - \BesselJ{\the\BesselOrderMinusOne}) 
}

\def\BesselJ#1{%
    \BesselOrder=#1%
    \BesselOrderMinusOne = \BesselOrder%
    \advance\BesselOrderMinusOne by -1%
    \ifnum\BesselOrder = 0
        \let\next=\BesselZERO
    \fi
    \ifnum\BesselOrder = 1
        \let\next = \BesselONE
    \fi
    \ifnum\BesselOrder > 1 
        \let\next = \Recursion
    \fi
    \next
}

решение1

% This is to be compiled with e-TeX. (Not TeX and also not LaTeX.)

\overfullrule=0pt
\parindent=0ex
\parskip=\baselineskip
\begingroup\catcode`\%=12 \lowercase{\endgroup\def\percentchar{%}}%

% Pete's bessel-routine:
% ======================

\newcount\BesselOrder
\newcount\BesselOrderMinusOne

\def\BesselZERO{besj0(x)}
\def\BesselONE{besj1(x)}

\def\Recursion{%
\advance\BesselOrder by -1
\advance\BesselOrderMinusOne by -1
((2 * \the\BesselOrder/ x) * {\BesselJ{\the\BesselOrder}} - \BesselJ{\the\BesselOrderMinusOne})
}

\def\BesselJ#1{%
    \BesselOrder=#1%
    \BesselOrderMinusOne = \BesselOrder%
    \advance\BesselOrderMinusOne by -1%
    \ifnum\BesselOrder = 0
        \let\next=\BesselZERO
    \fi
    \ifnum\BesselOrder = 1
        \let\next = \BesselONE
    \fi
    \ifnum\BesselOrder > 1 
        \let\next = \Recursion
    \fi
    \next
}

% Ulrich's bessel-routine:
% ========================
%
% The routine doesn't need temporary assignments and the like and is based
% on expansion only.
% 
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
% !!!! Due to the \numexpr-thingie e-TeX-extensions are required. !!!!
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%
% The routine as a trick for triggering expansion uses \romannumeral-expansion:
% When due to \romannumeral (La)TeX does gather together a sequence of digits
% trailed by a space as the number which it has to convert, expandable tokens
% get expanded.
% When in the end a number is gathered together which is not positive, as the result
% of the conversion (La)TeX will not deliver any token at all.
% Thus one can nicely (ab)use \romannumeral for triggering a lot of
% expansion-work and flipping-arguments-around-work as long as one ensures
% that in the end \romannumeral will not find a positive number.
%
% Due to \romannumeral-expansion \UDBesselJ will deliver the result in
% two expansion-steps/after "being hit" by two \expandafter .
%
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
% !!! \UDBesselJ will take its toll at the semantic nest and at the input-stack. !!!
% !!!                                                                            !!!
% !!! Don't use it with all too large values in the argument.                    !!!
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

\long\def\exchange#1#2{#2#1}%
\long\def\passfirsttosecond#1#2{#2{#1}}%
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\romannumeralstop{ }%

\def\UDBesselJ#1{%
  \romannumeral0%
  \ifnum#1 = 0 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
  {\romannumeralstop besj0(x)}{%
    \ifnum#1 = 1 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
    {\romannumeralstop besj1(x)}{%
      \ifnum#1 > 1 \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
      {%
        \expandafter\exchange\expandafter{%
          \romannumeral0%
          \exchange{ }{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter}%
          \expandafter\UDBesselJ\expandafter{\the\numexpr#1-2\relax}) %
        }{%
          \expandafter\passfirsttosecond\expandafter{%
            \romannumeral0%
            \exchange{ }{\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter}%
            \expandafter\UDBesselJ\expandafter{\the\numexpr#1-1\relax}%
          }%
          {\expandafter\exchange\expandafter{\the\numexpr#1-1\relax}{\romannumeralstop((2 * }/ x) * } - %
        }%
      }{\romannumeralstop}%
    }%   
  }%
}%

% Testing the routines:
% =====================

{\tt\string\BesselJ\string{4\string}} yields:\hfil\break
\BesselJ{4}

\hbox to\hsize{\null\hrulefill\null}\nointerlineskip

{\tt\string\UDBesselJ\string{4\string}} yields:\hfil\break
\UDBesselJ{4}

\hbox to\hsize{\null\hrulefill\null}\nointerlineskip

{\tt\string\expandafter\string\expandafter\string\expandafter\string\def\hfil\break
\string\expandafter\string\expandafter\string\expandafter\string\secondformula\hfil\break
\string\expandafter\string\expandafter\string\expandafter\string{\percentchar\hfil\break
\string\UDBesselJ\string{4\string}\string}}

yields the macro
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\secondformula
\expandafter\expandafter\expandafter{%
\UDBesselJ{4}}%
{\tt\string\secondformula:}

{\tt\meaning\secondformula}

\hbox to\hsize{\null\hrulefill\null}\nointerlineskip

{\tt\string\secondformula} yields:\hfil\break
\secondformula

\bye

введите описание изображения здесь

Связанный контент