Let's see the matter in general, though a deep discussion would require many pages of a book.
You are concerned with definitions of commands, not only with nesting macro calls. The "working" definition
\def\const#1#2{\expandafter\def\csname#1\endcsname{#2}}
with the call
\const{Count}{\length{\list}}
is equivalent to
\def\Count{\length{\list}}
If you have also \def\list{1,2,3}
, then
\const{Count}{\length{\list}}\Count
would print 3. However, if you say
\def\list{1,2,3}
\const{Count}{\length{\list}}
\Count
\def\list{a,b,c,d}
\Count
you'd get
3
4
Why? Because the macro \Count
is defined in terms of \list
, which will then use the current meaning of \list
, not the one at definition time: \list
is just a pointer to a token list (the current replacement text).
Your problem is to assign as the meaning \Count
the current length of \list
, independently from possible subsequent redefinitions. And you want it as a plain number, because you must pass it to \pstVerb
as the replacement text of a PostScript token.
The way to cope with this is to perform the computations, store the numeric result in a temporary control sequence and then using \edef
.
Here's a way:
\makeatletter
\newcount\const@count
\def\length#1{%
\const@count=\z@
\@for\next:=#1\do{\advance\const@count\@ne}%
\edef\@tempa{\number\const@count}%
}
\def\const#1#2{%
#2%
\expandafter\let\csname #1\endcsname\@tempa
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#1 \@tempa\space def}}\x
}
\makeatother
Call this as
\const{Count}{\length{\list}}
The important thing is to perform the computation before defining \Count
and doing \pstVerb
.
This is analogous to what you're doing elsewhere with \FPeval
.
First of all \length{\list}
is computed and the result is stored in \@tempa
with \edef
, so that the actual number is the replacement text. Then \let
will make \Count
have the current meaning of \@tempa
and then the \pstVerb
is emitted, in an indirect way, to avoid any reference to \@tempa
in the replacement text, thanks to \edef
again.
Let' try to generalize this; I suggest a three argument macro:
\makeatletter
\def\const#1#2#3{% #1=name, #2=method, #3=data
#2{#1}{#3}%
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#1 \csname#1\endcsname\space def}}\x
}
\newcount\const@count
\def\length#1#2{%
\const@count=\z@
\@for\next:=#2\do{\advance\const@count\@ne}%
\expandafter\edef\csname#1\endcsname{\number\const@count}%
}
\makeatother
Now \const{Count}{\length}{\list}
or \const{ABC}{\FPeval}{2*3}
will work.
If \FPeval
is the default method, you can simplify the syntax:
\documentclass{article}
\usepackage{pstricks-add,fp}
% user defined data
\def\list{1,2,3,4,5,6}
\makeatletter
\newcommand\const[3][\FPeval]{% #1=method, #2=name, #3=data
\expandafter#1\csname#2\endcsname{#3}%
\begingroup\edef\x{\endgroup
\noexpand\pstVerb{/#2 \csname#2\endcsname\space def}}\x
}
\newcount\const@count
\def\length#1#2{%
\const@count=\z@
\@for\next:=#2\do{\advance\const@count\@ne}%
\edef#1{\number\const@count}%
}
\makeatother
\begin{document}
\const[\length]{Count}{\list}
\Count
\const{ABC}{2*2}
\ABC
\end{document}