GeneralCalling macros with arguments - using \csname

LaTeX specific issues not fitting into one of the other forums of this category.
phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm

Calling macros with arguments - using \csname

Post by phi »

gkamel wrote:and I'm using your suggestion:

Code: Select all

\expandafter\def\csname temp\endcsname#1{Some code #1}

to define a new macro called MyMacro.
No, this defines a macro named temp. Make sure you understand what \csname actually does before trying to use it in more complicated situations.

Code: Select all

\expandafter\def\csname\temp\endcsname#1{Some code #1}

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Calling macros with arguments - using \csname

Post by josephwright »

\csname expands whatever it contains until it has an unexpandable list of tokens to use to create a name. So if you want to define a macro using the content of \temp:

Code: Select all

\def\temp{MyMacro}
\expandafter\def\csname\temp\endcsname#1{Some macro #1}
creates a macro called \MyMacro (or whatever is currently in \temp).
Joseph Wright
gkamel
Posts: 25
Joined: Thu Oct 30, 2008 1:53 pm

Re: Calling macros with arguments - using \csname

Post by gkamel »

Thanks for your replies.

I used what you suggested at some point, but my problem is, apparently, more fundamental, as the macro definition is nested inside another macro, which causes a "missing \endcsname inserted" error. Anyhow, I will try and figure it out.

Many thanks,

George
George Kamel
josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Re: Calling macros with arguments - using \csname

Post by josephwright »

On its own, that should not be a problem (although you may need to double-up # symbols). Can you post what you are actually doing?
Joseph Wright
gkamel
Posts: 25
Joined: Thu Oct 30, 2008 1:53 pm

Calling macros with arguments - using \csname

Post by gkamel »

Okay, here goes:

I have defined the following Macro:

Code: Select all

\newcommand*\CheckCountAssign[2]{
  \ifcsdef{#1}{
    \stepcounter{#2}
    \def\temp{#2\Numberstring{#2}}
    \expandafter\def\expandafter\csname\temp\endcsname{\csname#1\endcsname}
  }{}
}
the aim of which is to check if a macro (#1) is defined, and if so, assign it to a new macro with the string <counter name><counter value as a string>

So for example, with the following

Code: Select all

\def\SomeMacro#1{Hello #1!}

\newcounter{MacroNumber}

\CheckCountAssign{SomeMacro}{MacroNumber}

\MacroNumberOne{world}
the output should be: Hello world!, but I get the error:

Code: Select all

! Extra \endcsname.
<argument> ...xpandafter \csname \temp \endcsname
                                                  {\csname SomeMacro\endcsna...
l.67 \CheckCountAssign{SomeMacro}{MacroNumber}
I'm quite lost when it comes to understanding (La)TeX errors, so even a few hints as to how to solve it would be greatly appreciated.

Thanks,

George
George Kamel
phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm

Re: Calling macros with arguments - using \csname

Post by phi »

My guess is that \Numberstring is not expandable. Please provide an MWE.
gkamel
Posts: 25
Joined: Thu Oct 30, 2008 1:53 pm

Calling macros with arguments - using \csname

Post by gkamel »

\Numberstring appears to work okay, as calling \temp will output what it's supposed to, but it's the line after \Numberstring that's causing problems...

Code: Select all

\documentclass{article}

\usepackage{fmtcount}
\usepackage{etoolbox}

\begin{document}

\newcommand*\CheckCountAssign[2]{
  \ifcsdef{#1}{
  \stepcounter{#2}
  \def\temp{#2\Numberstring{#2}}
  % everything works fine upto this point.
  \expandafter\def\expandafter\csname\temp\endcsname{\csname#1\endcsname}
}{}
}


\def\SomeMacro#1{Hello #1!}
\newcounter{MacroNumber}
\CheckCountAssign{SomeMacro}{MacroNumber}
\MacroNumberOne{world}

\end{document}
Many thanks,

George
George Kamel
phi
Posts: 577
Joined: Tue Oct 21, 2008 8:10 pm

Calling macros with arguments - using \csname

Post by phi »

gkamel wrote:\Numberstring appears to work okay, as calling \temp will output what it's supposed to
this has nothing to do with expandibility. The full expansion of \Numberstring doesn't consist of only character tokens because it contains the unexpandable tokens \relax (via \protect) and \futurelet (via \@ifnextchar). You cannot use \Numberstring here.
josephwright
Site Moderator
Posts: 814
Joined: Tue Jul 01, 2008 2:19 pm

Calling macros with arguments - using \csname

Post by josephwright »

What you need to understand here is that \csname ... \endcsname "expands" things until it has a string of character tokens (letters, numbers, spaces, punctuation, etc.). However, there are some things which don't expand but also aren't characters. A classic one is \relax, which does nothing but is "unexpandable".

There is a crucial difference between getting TeX to print something (where \relax is executed, does nothing and disappears) and expand something. For example, if I write:

Code: Select all

Hello{\relax}World
I get no spaces and the definition of \relax "disappears". However, if I do:

Code: Select all

\edef\temp{\relax}
\show\temp
The expanded definition (\edef) does not make \relax disappear: the definition of \temp still contains \relax. If I then tried:

Code: Select all

\expandafter\def\newtemp\csname \temp\encsname
I'd get a complaint from TeX.

The non-expandability of some macros is a pain. However, a simple test is do \edef the content then \show it (as I've done above). If there is anything left other than characters, \csname will not work.
Joseph Wright
User avatar
nlct
Posts: 276
Joined: Thu Nov 06, 2008 11:15 am

Calling macros with arguments - using \csname

Post by nlct »

Try using \storeNumberstring instead of \Numberstring. For example:

Code: Select all

\storeNumberstring{mynumber}{#2}%
 \edef\temp{#2\FMCuse{mynumber}}%
Regards
Nicola Talbot
Post Reply