0

How can I bind the command to the output of another command, determined at the time the command is bound?

For example with the following code,

\newcommand{\hello}{foo}
\newcommand{\world}{\hello}
\renewcommand{\hello}{bar}
\world % outputs 'bar'

how can I modify the second line so that running \world after the third line executes will output foo?

  • 6
    \let\world\hello – Ulrike Fischer Jul 2 '14 at 15:07
  • @UlrikeFischer That only works if there is a single layer of expansion, doesn't it? For example, after \newcommand{\hi}{foo} \newcommand{\hello}{\hi} \let\world\hello \renewcommand{\hi}{bar}, \world will expand as bar. – T. Verron Jul 2 '14 at 15:24
  • Is there a way to redefine a macro created using \let? – xsznix Jul 2 '14 at 15:39
  • 2
    @xsznix a macro defined with \let is exactly the same as one defined with \newcommand so \renewcommand will redefine it – David Carlisle Jul 2 '14 at 15:46
  • What do you take for "output of a command", e.g., the output of \hello? The \meaning of \hello? The tokens that form the top-level-expansion of \hello? The tokens that form the complete expansion of \hello? The boxes produced due to \hello? Some of the content of the .pdf-output-file? With \let\world\hello the macro \world will have the meaning which \hello has at the time of performing the \let-assignment. – Ulrich Diez Mar 22 at 12:03
1

As long as argument-processing and is not an issue, you can pass the top-level-expansion of \hello as definition-text to \world:

\newcommand{\hello}{foo}
\expandafter\newcommand\expandafter{\expandafter\world\expandafter}\expandafter{\hello}
\renewcommand{\hello}{bar}
\world % expands to "foo"

or

\newcommand\passfirsttosecond[2]{#2{#1}}
\newcommand{\hello}{foo}
\expandafter\passfirsttosecond\expandafter{\hello}{\newcommand{\world}}
\renewcommand{\hello}{bar}
\world % expands to "foo"

Via \let you can assign \world the meaning of \hello at the time of performimng the \let-assignment:

\newcommand{\hello}{foo}
\newcommand\world{}% <- just to make sure an error-message
                   %     is raised in case \world is already defined.
\let\world=\hello
\renewcommand{\hello}{bar}
\world % expands to "foo"

If you need deeper levels of expansion, you can probably have the assignment for defining \world performed in terms of \edef or \protected@edef:

\newcommand{\hello}{foo}
\newcommand\world{}% <- just to make sure an error-message
                   %     is raised in case \world is already defined.
\edef\world{\hello}
\renewcommand{\hello}{bar}
\world % expands to "foo"

or

\newcommand{\hello}{foo}
\newcommand\world{}% <- just to make sure an error-message
                   %     is raised in case \world is already defined.
\begingroup
\makeatletter
\@firstofone{%
  \endgroup
  \protected@edef\world{\hello}%
}%
\renewcommand{\hello}{bar}
\world % expands to "foo"
0

The following shows two ways of achieving your aim: Version 1 uses \let as suggested by Ulrike Fischer in the comments. Version 2 uses \edef which you should only use if you need to expand previous content as T. Verron noted in the comments. Both will output foo.

\documentclass{article}
\begin{document}
% Option 1: let
\newcommand{\hello}{foo}
\let\world\hello
\renewcommand{\hello}{bar}
\world

% Option 2: edef
\newcommand{\hi}{foo}
\newcommand{\Hello}{\hi}
\edef\world{\Hello}
\renewcommand{\hi}{bar}
\world
\end{document}

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.