local variables

  • Follow


Good day!

I'd like to construct some strings (actually, names of TIKZ nodes /
coordinates, but my problem is independent of TIKZ). As they should be
constructed in a consistent way, I'd like to use a macro (\getposname)
for this task. In this macro, I'd like to use something like local
variables. Unfortunately, it is not obvious to me, how to achieve
this. The following minimized example shows the problem:

----------------------------
\documentclass{article}
\begin{document}

\def\getposname{%
        \def\dummy{foo}% comment this line to get \coordinate to work
        bar% (actually something more involved using \dummy, where
           % \getposname takes 2 parameters and \dummy contains
#1 ...)
}

\edef\myvar{\getposname} % fails with:
%! Undefined control sequence.
%\getposname ->\def \dummy
%                          {foo}bar
%l.11 \edef\myvar{\getposname
%                            } % fails with:
%?

\getposname % works always, shows bar (as expected)

\end{document}
----------------------------

Why would the macro fail in the first case and succeed in the other?

Is there a way to get the first call to work?

TIA
0
Reply carsten.scholtes (3) 3/28/2011 3:17:48 PM

le 28/03/2011 17:17 selon c.scholtes:
> Good day!
> 
> I'd like to construct some strings (actually, names of TIKZ nodes /
> coordinates, but my problem is independent of TIKZ). As they should be
> constructed in a consistent way, I'd like to use a macro (\getposname)
> for this task. In this macro, I'd like to use something like local
> variables. Unfortunately, it is not obvious to me, how to achieve
> this. The following minimized example shows the problem:
> 
> ----------------------------
> \documentclass{article}
> \begin{document}
> 
> \def\getposname{%
>         \def\dummy{foo}% comment this line to get \coordinate to work
>         bar% (actually something more involved using \dummy, where
>            % \getposname takes 2 parameters and \dummy contains
> #1 ...)
> }
> 
> \edef\myvar{\getposname} % fails with:
> %! Undefined control sequence.
> %\getposname ->\def \dummy
> %                          {foo}bar
> %l.11 \edef\myvar{\getposname
> %                            } % fails with:
> %?
> 
> \getposname % works always, shows bar (as expected)
> 
> \end{document}
> ----------------------------
> 
> Why would the macro fail in the first case and succeed in the other?
> 
> Is there a way to get the first call to work?
> 
> TIA

don't you want something rather like this:

\documentclass{minimal}
\begin{document}

\def\getposname{\edef\dummy{\foo}%
        \dummy}

\def\foo{foo}

\getposname

\def\foo{bar}

\getposname

\def\foo{blob}

\getposname

\end{document}

regards, 
Jean-Francois
0
Reply Jean 3/28/2011 3:40:42 PM


c.scholtes wrote:

> I'd like to use something like local
> variables.

"variable" is a concept of e.g., procedural or object oriented 
programming languages like pascal, c or c++ or whatever 
while (La)TeX is a macro-language.

There are integer-parameters, registers, macros, primitives,
expansion and assignments in (La)TeX. 

> Unfortunately, it is not obvious to me, how to achieve
> this. The following minimized example shows the problem:
> 
> ----------------------------
> \documentclass{article}
> \begin{document}
> 
> \def\getposname{%
>         \def\dummy{foo}% comment this line to get \coordinate to work
>         bar% (actually something more involved using \dummy, where
>            % \getposname takes 2 parameters and \dummy contains
> #1 ...)
> }
> 
> \edef\myvar{\getposname} % fails with:
> %! Undefined control sequence.
> %\getposname ->\def \dummy
> %                          {foo}bar
> %l.11 \edef\myvar{\getposname
> %                            } % fails with:
> %?
> 
> \getposname % works always, shows bar (as expected)
> 
> \end{document}
> ----------------------------
> 
> Why would the macro fail in the first case and succeed in the other?

The first case is about trying to use \getposname within \edef.
The crucial point is that \edef does perform macro-expansion,
but does not perform assignments that might possibly be contained
in its' definition-text (e.g., does not execute  \def or \let or \edef). 
In case a token is undefined while attempting to expand it, an
error-message will be raised.

With 

  \edef\myvar{\getposname}

, \getposname will be expanded to  

   \def\dummy{foo}bar  .

In further \edef-evaluation, \def will be left untouched as it is
defined and not expandable and an attempt of expanding
\dummy will take place while \dummy is still undefined
due to the \def-assignment not being carried out, which 
implies raising an error-message about \dummy being
undefined.

See, \def or \let are not expandable macros but they are 
unexpandable primitives which can reach TeX's "stomach".

[If you are interested in the "anatomy" of TeX, have a look at
section 11 of David Salomon,  An introduction to TeX, part 1,
NTG course june 1992
(http://www.tex.ac.uk/tex-archive/usergrps/ntg/maps/maps08/maps08_i.ps.gz ) ]

> Is there a way to get the first call to work?

You can't perform an assignment from within an \edef or \xdef
as those are assignments themselves, but you can try
LaTeX' \DeclareRobustCommand or \protect-mechanism
with \protected@edef instead of \edef in order to delay the
assignment:


\documentclass{article}

\DeclareRobustCommand*\dummydefiner{\def\dummy}

\begin{document}

\def\getposname{\dummydefiner{foo}bar}

\makeatletter
\protected@edef\myvar{\getposname}
\makeatother

% now the \def\dummy/\dummydefiner-assignment is not
% carried out at the time of defining \myvar but is attempted to be
% carried out whenever \myvar gets expanded in non-expansion-
% contexts - that is outside things like \edef,  \xdef or \csname..
\show\myvar

\myvar

\getposname % works always, shows bar (as expected)

\end{document}



Ulrich
0
Reply Ulrich 3/28/2011 5:17:27 PM

Dear Jean Francois,

Thank you for your quick answer. Unfortunately, your proposition
does not appear to be applicable to my problem:
I will have to use the result of \getposname in an "expanding"
context (as a coordinate name in TIKZ, as in e.g.
"\draw (\getposname) -- (0,0);"). In this situation,
the \edef contained in the value of the macro
still leads to the error explained by Ulrich.o

Best regards

Carsten
0
Reply carsten.scholtes (3) 3/30/2011 10:37:42 AM

Dear Ulrich,

Thank you very much for your elaborate and enlightening answer.
I can now understand why my code fails in the way it does.
I was not aware of the selective expansion
in the template part of an \edef.
The link you provided was also very informative.
(Among many other things, it pointed me to the very
helpful \tracingmacros...)

Trying to apply your solution to my problem, I still had
difficulties: I want to use the value of \dummy
for constructing the result of \getposname (not simply "bar").
When I try to do so, \dummy appears to be undefined...
Additionally, the result is to be used as
the name of a TIKZ coordinate / node and this use
appears to be in an expanding context similar to \edef.
I don't really understand what \protect is supposed to achieve
but I'm afraid, the result would still not be accepted.

In the meantime, I found some ugly workaround (involving
much verbosity and code replication) for my current needs.
Having spent already way too much time on this,
that'll have to do, for now.

Again, thank you very much for your inspiring input.

Best regards

Carsten
0
Reply carsten.scholtes (3) 3/30/2011 10:39:19 AM

4 Replies
382 Views

(page loaded in 0.092 seconds)

Similiar Articles:













7/23/2012 5:18:03 PM


Reply: