Using \let with \csname inside a macro
The problem with the OP's syntax is that the first \csname
of the \let
was expanded into a token, but not the 2nd. One nice trick (learned from David C) is that you can insert \expandafter
inside a \csname
, just before the \endcsname
, to expand the next thing that follows, before closing out the first \csname
expansion! That is what I do here, so that both \csname
s are expanded into cs-tokens, before the \let
is evaluated.
\documentclass{article}
\newcommand*\letprefix[2]{%
\expandafter\let\csname#1\expandafter\endcsname\csname#1#2\endcsname}
\newcommand*\mycommandversion{I want to use this as ``\textbackslash
mycommand''}
\letprefix{mycommand}{version}
\begin{document}
Hello!
\mycommand
\end{document}
With etoolbox
you already have a handy tool:
\documentclass{article}
\usepackage{etoolbox}
\newcommand*\letprefix[2]{%
\csletcs{#1}{#1#2}%
}
\newcommand*\mycommandversion{I want to use this as ``\textbackslash mycommand''}
\letprefix{mycommand}{version}
\begin{document}
Hello!
\mycommand
\end{document}
No need to remember complex sequences of \expandafter
.
The answer of Steven B. Segletes says it all.
An alternative less efficient approach is exchanging tokens after applying \csname..\endcsname
:
\documentclass{article}
\newcommand\exchange[2]{#2#1}%
\newcommand*\letprefix[2]{%
\expandafter\exchange\expandafter{\csname#1#2\endcsname}{%
\expandafter\let\csname#1\endcsname= %
}%
}%
\newcommand*\mycommandversion{%
I want to use this as ``\textbackslash mycommand''%
}%
\letprefix{mycommand}{version}
\begin{document}
Hello!
\mycommand
\end{document}
(The image comes from a link to the .jpg-file of Steven B. Segletes' answer.)
A more "generic" approach to the matter could be a macro \NameToCs
:
The TeXbook explains a nice feature when it comes to defining macros: In the ⟨parameter text⟩
of a macro-definition you can use #{
-notation for a macro whose last argument will be delimited by a left curly brace {
which—unlike other argument-delimiters—will be re-inserted as if it had been left in place.
Thus I sometimes use a macro-mechanism \NameToCs
which processes an argument which is delimited by a left curly brace ({
) and another argument which is nested in curly braces.
The argument nested in curly braces is taken for the name of a ⟨control sequence token⟩
which is to be constructed via \csname
..\endcsname
.
\NameToCs
works as follows:
\NameToCs⟨stuff not in curly braces⟩{NameOfCs}
→
⟨stuff not in curly braces⟩\NameOfCs
(If you wish to obtain only the control-sequence-token \NameOfCs
, then you can leave ⟨stuff not in curly braces⟩
empty: \NameToCs{NameOfCs} → \NameOfCs
)
\makeatletter
\newcommand\exchange[2]{#2#1}%
\@ifdefinable\NameToCs{\long\def\NameToCs#1#{\romannumeral0\innerNameToCs{#1}}}%
\newcommand\innerNameToCs[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\makeatother
There are various uses for such a macro:
\NameToCs{foo}
→\foo
\NameToCs\string{foo}
→\string\foo
\NameToCs\meaning{foo}
→\meaning\foo
\NameToCs\global\long\def{foo}...
→\global\long\def\foo...
\NameToCs\newcommand*{foo}...
→\newcommand*\foo...
\NameToCs\NameToCs\global\let{foo}={bar}
→\NameToCs\global\let\foo={bar}
→\global\let\foo=\bar
Usage-example 6 can be applied in your scenario:
\documentclass{article}
\makeatletter
\newcommand\exchange[2]{#2#1}%
\@ifdefinable\NameToCs{\long\def\NameToCs#1#{\romannumeral0\innerNameToCs{#1}}}%
\newcommand\innerNameToCs[2]{\expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}}%
\makeatother
\newcommand*\mycommandversion{%
I want to use this as ``\textbackslash mycommand''%
}%
\newcommand*\letprefix[2]{%
\NameToCs\NameToCs\let{#1}= {#1#2}%
}%
\letprefix{mycommand}{version}
\begin{document}
Hello!
\mycommand
\end{document}
(The image comes from a link to the .jpg-file of Steven B. Segletes' answer.)
Be aware that a simple \let
-assignment does not always work out for control-sequences which initiate the carrying-out of a "macro-based mechanism" that internally consists of several macros.
- This is the case, e.g., with LaTeX commands that process optional arguments defined in terms of
\newcommand
or with LaTeX commands that are defined as robust macros by\DeclareRobustCommand
.
With such commands the command\LetLtxMacro
of the package letltxmacro takes care of the internal macros also. - This is also the case with commands defined in terms of
xparse
's\NewDocumentCommand
.