# Expanding macros within \csname

I have some macros that expand to some text but when used together they should expand to something completely different. In this example:

• \foo -> x
• \bar -> y
• \foo\bar -> Hello World

Doing it with \if... constructions works in principle, but requires a lot of typing, so I tried it with \csname, but couldn't get it to work:

\documentclass{article}

\newcounter{mycounter}

\def\bar{\ifalternatetext{y}{z}}

\def\bazxy{Hello World}

\newcommand\print[2]{\csname baz#1#2\endcsname{}}

\begin{document}
This works: \print{x}{y}'

This doesn't: \print{\foo}{\bar}'
\end{document}

• Omit the {} after \foo{} and \bar{}
– user31729
Dec 28, 2014 at 10:22
• Works for the example as originally posted, but not for the real document, modified the example to reflect this. Dec 28, 2014 at 11:50
• I don't see how is \emph a good thing to put inside \csname. What do you really want?
– yo'
Dec 28, 2014 at 12:05
• Right. That was a case of "cutting away too much on the way to the MWE", using \emph instead of the counter stuff I actually have there. Causes the same message (and what I really want is that message not appearing anymore), but is confusing to the reader. Modified it accordingly. Dec 28, 2014 at 12:49
• @user66554: My solution worked right out of the box... if you changed the question/code it's quite natural that in most cases a provided solution will not work any longer. What do you expect me do now?
– user31729
Dec 28, 2014 at 13:20

The {} brackets after \foo and \bar prevent the expansion of the the macros in the OP's second call to \print.

\documentclass{article}

\def\foo{x}
\def\bar{y}

\def\bazxy{Hello World}

\newcommand\print[2]{\csname baz#1#2\endcsname{}}

\begin{document}
This works: \print{x}{y}'

This also works: \print{\foo}{\bar}'
\end{document}

• +1 Yes, for the version as originally posted - but that one did nothing instead of complaining missing \endcsname as in my original document. I managed to reproduce the behaviour by adding \emph{}, but now your solution doesn't work anymore. And what would I have done if \foo and \bar had taken arguments and should not have been followed by a space? (they don't, though the macros called within them do.) Dec 28, 2014 at 11:49
• @user66554: I will look later on
– user31729
Dec 28, 2014 at 12:16

You can't do assignments inside \csname...\endcsname. A good reference is What exactly do \csname and \endcsname do? and my answer to it where you find

It's possible to give many other interesting uses of this trick. But one should always keep in mind that TeX does complete expansion of what it finds in that context and that only characters must remain.

Since \addtocounter{mycounter}{1} relies on eventually doing \global\advance\c@mycounter by 1 it is not allowed in \csname...\endcsname.

If all you want is to have \foo behaving differently if followed by \bar or not, use \@ifnextchar:

\makeatletter
\newcommand{\foo}{\@ifnextchar\baz{\foobaz\@gobble}{x}}
\newcommand{\baz}{y}
\newcommand{\foobaz}{Hello world}
\makeatother


Note that \@gobble will remove the superfluous \baz token.

Complete example

\documentclass{article}

\makeatletter
\newcommand{\foo}{\@ifnextchar\baz{\foobaz\@gobble}{x}}
\newcommand{\baz}{y}
\newcommand{\foobaz}{Hello world}
\makeatother

\begin{document}
Separate: \foo{} and \baz.

Contiguous: \foo\baz
\end{document}


Here's a different approach with your \print macro:

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\providecommand\@secondofthree[3]{#2}
\providecommand\@thirdofthree[3]{#3}

\newcommand{\foo}{x\expandafter\@secondofthree}
\newcommand{\fuu}{T\expandafter\@secondofthree}
\newcommand{\baz}{\@secondoftwo{y}{z}}
\makeatother

\newcommand\bazz{Normal}
\newcommand\bazTy{Ops}
\newcommand\bazxy{Hello World}

\newcommand\print[2]{\csname baz#1#2\endcsname}

\begin{document}

\print{\foo}{\baz}'

\print{\fuu}{\baz}'

\print{}{\baz}'

\end{document}


The macro \print{\foo}{\baz} becomes

\csname baz\foo\baz\endcsname


and, expanding \foo.

\csname bazx\expandafter\@secondofthree\baz\endcsname


Now \expandafter causes the expansion of \baz and disappears

\csname bazx\@secondofthree\@secondoftwo{y}{z}\endcsname


where the expansion of \@secondofthree selects y, giving

\csname bazxy\endcsname


When \print{}{\baz} is used, we have

\csname baz\@secondoftwo{y}{z}\endcsname


and \@secondoftwo selects z, giving \csname bazz\endcsname.

One can install an abstraction layer that eventually does the same, but makes definitions easier:

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\providecommand\@secondofthree[3]{#2}
\providecommand\@thirdofthree[3]{#3}

\newcommand{\newprefixcommand}[2]{%
\newcommand{#1}{#2\expandafter\@secondofthree}%
}
\newcommand{\newalternatecommand}[3]{%
\newcommand{#1}{\@secondoftwo{#2}{#3}}%
}
\makeatother

\newcommand\print[2]{\csname baz#1#2\endcsname}

\newprefixcommand{\foo}{x}
\newprefixcommand{\fuu}{T}
\newalternatecommand{\baz}{y}{z}

\newcommand\bazz{Normal}
\newcommand\bazTy{Ops}
\newcommand\bazxy{Hello World}

\begin{document}

\print{\foo}{\baz}'

\print{\fuu}{\baz}'

\print{}{\baz}'

\end{document}

• There are several dozen foos and bars each, making the \if...-based approach rather cumbersome. I thought I could use \let or something to evaluate \foo\bar to make the assignments and assign the result to a new, temporary macro containing no assignments which then could be used in \csname, but that didn't work. Dec 28, 2014 at 13:56
• @user66554 You have better ask a new question, stating precisely your aim, with a sensible minimal example. Dec 28, 2014 at 13:58
• @user66554 I added a different approach with your \print macro. Dec 28, 2014 at 14:35

Instead of putting \foo and \bar directly into the \csname I now have \foo and \bar assign a temporary macro which then can be used within \csname:

\documentclass{article}
\usepackage{etoolbox}

\newcounter{@mycounter}

\makeatletter

\def\@foo@out{}
\def\@bar@out{}

\newcommand\ifalternatetext[2]{%
\ifnumcomp{\value{@mycounter}}{>}{0}{%
\gdef\@bar@out{#1}%
}{%
\gdef\@bar@out{#2}%
}}

\newcommand\@foohelper[1]{%
\gdef\@foo@out{#1}%
}

\def\foo{\@foohelper{x}}
\def\bar{\ifalternatetext{y}{z}}

\def\bazxy{Hello World}

\newcommand\print[2]{#1#2\csname baz\@foo@out\@bar@out\endcsname{}}

\makeatother

\begin{document}
\print{\foo}{\bar}'
\end{document}
`