(This answer is really a long rant about “functions”, but may help you anyway…)
Calling package function inside a package function […]
I want to use function […]
When I want to use the zz function inside of package's function […]
I am trying to call the xx function inside a function
There are no functions in TeX. It only has macros, which are simply text (token) substitution.
This distinction matters because from most typical programming languages, you may expect functions to behave in certain ways:
It is possible to tell, from looking at the place where a function is referenced, how many arguments it takes and where its “region of influence” (in the input text) ends. For example, in most languages if you saw f(a, b); g(c)
, you would know that the function f
takes two arguments a
and b
, and that g
is another function that is “called” after f
is. In TeX, if you see \f{a}{b}\g{c}
, then anything is possible:
- maybe
\f
takes zero or one parameters (leaving {a}{b}
or {b}
remaining on the input stream),
- maybe it takes exactly two,
- maybe it even takes three or four (so that the token
\g
is one of the parameters passed to \f
),
- maybe it takes even more,
- maybe things will fail with
Use of \f does not match its definition
,
- maybe
\f
only takes one parameter {a}
, but it expands to something that takes multiple parameters, and that thing will consume the \g
.
- maybe
\f
expands to different things in different circumstances, and in some cases consumes more tokens than in others.
Worse, all these patterns are in fact common in TeX code, such as in the definitions of macros in LaTeX and in packages. (It is only the external interface that LaTeX provides to the document author that is mostly consistent.) It is impossible to tell by looking at the source code like \f{a}{b}\g{c}
.
In a place where a value is expected, you can substitute a function call that returns a value. For example, if the function call g(2)
returns the value 21
, and if f
takes one argument, then writing f(g(2))
is (somewhat, modulo side-effects) equivalent to writing f(21)
. In TeX, writing \f{\g{2}}
will result in \f
getting the sequence of four tokens (\g
, {
, 2
, }
) as its #1
. (And all this is a simplification, as the situation can be different if catcodes are changed.)
(With all this in mind, you may want to consider whether you really want to program in TeX and whether it's something you may enjoy long-term… it can certainly be a fun puzzle but it can also be frustrating.)
In this case, the \zz
solution you got (and which is in the question) works like the following, in something like \zz{abc}
: First, \zz
gets the three tokens abc
. Then via clever expansions \zzz
is repeatedly left on the input stream, to consume, as its (#1
, #2
), the pairs (0, a
), (1, b
), (2, c
), (3, \relax
), after which it expands to 3.
Now in your case, with \zz{\mm@char}
, first \zz
will get the token \mm@char
as the parameter #1
, not the value of \mm@char
. (And if @
doesn't have the catcode of “letter”, it would get the sequence of five tokens (\mm
, @
, c
, h
, a
, r
) which is even worse.) This won't work because \zzz
expects to get characters, on which it does tests like \ifnum \expandafter `\string #2<"80
and with #2
being \mm@char
, this will not work.
In other words, you've run into the second problem mentioned above: unlike in most programming languages, even if \mm@char
is defined as something that expands to abc
, you cannot write \zz{\mm@char}
instead of \zz{abc}
.
The way to fix this will depend on the definition of \mm@char
(which you've not given):
- If
\mm@char
is something that expands to a sequence of characters in one expansion step, then you could use \expandafter\zz\expandafter{\mm@char}
which results in TeX actually seeing \zz{<expansion of \mm@char>}
.
- If
\mm@char
expands to its final sequence in two steps (that is, it expands to a macro which expands to the desired sequence of characters), you could do:
\expandafter\expandafter\expandafter\zz\expandafter\expandafter\expandafter{\mm@char}
which results in the input stream getting replaced first with \expandafter\zz\expandafter{<expansion of \mm@char>}
and then with \zz{<expansion of expansion of \mm@char>}
- If
\mm@char
expands to its final sequence in more steps, you'll need more \expandafter
s.
- And if
\mm@char
expands to multiple tokens (that are not what you want), or involves doing some state-changing computation (i.e. it involves commands that reach and are processed by TeX's “stomach”), then you'll have to find alternative solutions.
There's no other programming language I know of where instead of f(g(2))
you have to write different things based on how many steps g
takes. There's a way to rationalise all this within the terminology of functions (e.g. by saying the “type” of g
is different in those different cases), but it's better to instead use the right mental model: token substitution, not function calls.
\zz
is defined, but\xx
is used. The error is probably "Undefined control sequence". Also, the definition of\mm@char
is not shown. Depending on its definition, an expansion might help:\expandafter\zz\expandafter{\mm@char}
.