Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to create a pspicture with a variety of parameters which are interdependent. I'm using expl3 for the interface. But I get an error when I try to use \getr

Error: /undefined in \getr
Operand stack:
   --nostringval-- 56.9055  0.0

Initially, I had no ideas of where the error was arising from. I've now tried quite a few different ways to replicate the error. Most of them do not fail. The only time I get a fail is when I'm using xparse to define the interface I want.

Here's my MWE:

\documentclass{article}
\usepackage{xparse}
\usepackage{pst-eucl}
\usepackage[margin=1in]{geometry}
\psset{unit=1cm}
\pagestyle{empty}
%%
\ExplSyntaxOn
    \cs_generate_variant:Nn \int_eval:n {c}
    \NewDocumentCommand{\setr}{ m m }
        {
            \int_if_exist:cF { g__ace_angle_ #1 _int }
            { \int_new:c { g__ace_angle_ #1 _int }}
            \int_gset:cn  { g__ace_angle_ #1 _int }
                          {\int_eval:n {#2}}
        }
    \NewDocumentCommand{\getr}{ m }
        {
            \int_eval:c  { g__ace_angle_ #1 _int }
        }
    %%
    \setr{r1}{-30}
    \setr{u1}{\getr{r1}+90}
    %%
    \newcounter{dummy}\setcounter{dummy}{-30}
    \newcommand{\asimplecommand}{-30}
    \newcommand{\expliiimacro}{\int_eval:n {\asimplecommand + 60}}
    \newcommand{\argdependentmacro}[1]{\ifcase#1\relax-30\or0\or30\or60\fi}
    \NewDocumentCommand{\xparsemacroA}{ }{120}
    \NewDocumentCommand{\xparsemacroB}{ m }{#1}
    \cs_new:Npn \latexiiimacro #1 { #1 }
\ExplSyntaxOff
\setlength{\parindent}{0ex}
\setlength{\parskip}{5ex}
\begin{document}

Works:\hspace*{1in}\texttt{getr(r1)=}$\getr{r1}$\newline
Works:\hspace*{1in}\texttt{getr(u1)=}$\getr{u1}$
\vspace{1cm}

\textbf{It's not a problem with passing a counter-like thingy:}\newline
Works:  
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\thedummy]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{It's not a problem with a command:}\newline
Works:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\asimplecommand]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{It's not with a command name whose internals are defined with \texttt{expl3}:}\newline
Works:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\expliiimacro]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{It's not a problem with first having to evaluate an argument:}\newline
Works:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\argdependentmacro{2}]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{It's not a problem with command name defined in \texttt{latex3}:}\newline
Works:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\latexiiimacro{-120}]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{What about \texttt{xparse}:}\newline
Fails:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\xparsemacroA]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\textbf{What about \texttt{xparse}:}\newline
Fails:
\begin{pspicture}[shift=-1](-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}
    \pstRotation[RotAngle=\xparsemacroB{120}]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

Fails:
\begin{pspicture}(-1,-1)(1,1)
    \pstGeonode(0,0){o}(1,0){r}(0,1){u}
    \pstRotation[RotAngle=\getr{r1}]{o}{r}[r1] 
    \pstRotation[RotAngle=-60]{o}{r}[u1] 
\end{pspicture}

\end{document}

Producing:

enter image description here

Of all the methods I'm using, only xparse seems to result in the error:

 Error: /undefined in \xparsemacro

That's actually the last place I thought I'd have a problem. Any ideas?

share|improve this question
    
Look for \int_case:nnn to be used instead of \ifcase: it's much more flexible and it's expandable as well. –  egreg Jan 27 '13 at 11:58
    
Instead of \int_if_exist:cF {...} { \int_new:c {...} } I think you can use \int_gzero_new:c {...} which also sets the integer to zero if it is already defined. –  Bruno Le Floch Jan 27 '13 at 18:03
add comment

1 Answer 1

up vote 7 down vote accepted

The problem is expandability. When you have

\pstRotation[RotAngle=\SomeMacro{argument}]{o}{r}[r1] 

PStricks needs to be able to write the angle into the .dvi file, which is then used further down the line by PostScript. That works fine if \SomeMacro is expandable, as it gets turned into a number. However, if it is a protected (non-expandable) command then this will not work: instead the name of the command is written to the .dvi file, and this is then meaningless to PStricks.

LaTeX3 document commands are protected, as this makes most sense in almost all cases. There is, however, a method for creating expandable document commands

\DeclareExpandableDocumentCommand{\getr}{ m }
   {
     \int_use:c  { g__ace_angle_ #1 _int }
  }

If you use this for all of the 'get' functions, you find that the example then does compile.

share|improve this answer
    
Wouldn't \int_eval:n { \use:c {...} } be better? The fact that the c variant works is a bit of an artifact, in my opinion. –  egreg Jan 27 '13 at 11:43
    
@egreg Fixed: it should be \int_use:c as a variant on \int_use:N :-) –  Joseph Wright Jan 27 '13 at 11:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.