5

The following works as expected:

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \makeatletter
    \node (01) at (0, 0) {};
    \draw (0, 0) -- (0, 01);
    \makeatother
\end{tikzpicture}
\end{document}

But when I replace one of the 01s with \@ifnextchar1001, which should be equivalent according to my understanding, it breaks:

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \makeatletter
    \node (\@ifnextchar1001) at (0, 0) {};
    \makeatother
\end{tikzpicture}
\end{document}

gives

! Argument of \XC@definec@lor has an extra }.
<inserted text> 
                \par 
l.6   \node (\@ifnextchar1001)
                              at (0, 0) {};

and

\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    \makeatletter
    \draw (0, 0) -- (0, \@ifnextchar1001);
    \makeatother
\end{tikzpicture}
\end{document}

yields

! Argument of \XC@definec@lor has an extra }.
<inserted text> 
                \par 
l.6   \draw (0, 0) -- (0, \@ifnextchar1001)
                                          ;

What is the relevant difference between 01 and \@ifnextchar1001 in this case? How can I make this – or a similar construct – work as intended?

  • On another question, egreg pointed out that the XC@ prefix suggests that the problem might stem from within xcolor. Hence the color tag. – Hermann Döppes Jan 22 '17 at 01:45
  • For anyone interested: The problem I was trying to solve when walking into this gotcha was removing leading zeroes so TikZ would not try to parse them as octal. – Hermann Döppes Jan 22 '17 at 01:45
  • 1
    A lot of stuff is triggered by \begin{document}. It is good practice to make sure the cat codes are what LaTeX expects when that stuff gets executed. Hence, if you change them in the preamble, you change them back. If you change them in the document, you change them back before \end{document}. But you shouldn't usually change them in the document directly, of course. – cfr Jan 22 '17 at 04:13
  • Why don't you either use simple macro or use PGF's maths stuff? – cfr Jan 22 '17 at 04:14
  • @cfr Because I failed to find a simpler solution. (Actually, I'm currently working around it by specifying times as 9:50 instead of 09:50, so this is really not about the original problem.) – Hermann Döppes Jan 22 '17 at 04:20
  • If your aim is removing leading zeros, then \number is what you need. Can you please tell what's the expected result? – egreg Jan 22 '17 at 09:23
  • @egreg While this seems to solve my original problem, this question is about trying to understand why my ridiculously complicated approach does not work. – Hermann Döppes Jan 22 '17 at 09:31
  • 1
    @HermannDöppes Showing a call of \@ifnextchar1001 is not the best way to explain the problem you have. Yes, the ultimate reason is that \futurelet is involved, but that's all. – egreg Jan 22 '17 at 09:34

2 Answers2

5

\@ifnextchar is not expandable because of its internal use of \futurelet. A node name must be expandable, it is internally used inside \csname ...\endcsname.

If you just want to compare simple digits, then a test using the normal macro argument parsing is sufficient:

\documentclass{minimal}
\usepackage{tikz}

% \IfNextChar
% #1: the char for testing
% #2: code for true
% #3: code for false
% #4: next char
\makeatletter
\newcommand{\IfNextChar}[4]{%
  \ifx#1#4\@empty\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {#2}{#3}%
}
\makeatother

\begin{document}
\begin{tikzpicture}
    \node (\IfNextChar1001) at (0, 0) {};
\end{tikzpicture}
\end{document}

The same applies to the usage of \@ifnextchar as coordinate.

Heiko Oberdiek
  • 271,626
1

You can just convert the number from base 10 to base 10 using PGF math. Maybe overkill, maybe not.

\documentclass{article}
\usepackage{tikz}
\begin{document}
\pgfmathbasetodec{\myconvresult}{001}{10}
\pgfmathsetmacro\myresult{\myconvresult+1}\myresult

\pgfmathbasetodec{\myconvresult}{0214}{10}
\pgfmathsetmacro\myresult{\myconvresult+1}\myresult

\pgfmathbasetodec{\myconvresult}{000035}{10}
\pgfmathsetmacro\myresult{\myconvresult+1}\myresult

\pgfmathbasetodec{\myconvresult}{301}{10}
\pgfmathsetmacro\myresult{\myconvresult+1}\myresult
\end{document}

arithmetic in base 10

I'm surprised if there isn't a setting for this somewhere ....

cfr
  • 198,882
  • While this solves my original problem, it does not answer the question. (And I'm surprised I didn't find this. Need to step up my searching game.) – Hermann Döppes Jan 22 '17 at 04:35
  • Well, TikZ essentially defines its own parser, so using anything non-PGF low-level to parse things in that environment is likely to be fraught in various ways. And I don't think regular code would work in place as you're using it, even without the cat-code stuff. When you say \begin{tikzpicture}, you trigger code which sets the cat codes to what TikZ expects, so any changes you've made prior to that are not going to make any difference. Look at the utility code for PGF to see what I mean. So you need to use a macro or something here, I think. – cfr Jan 22 '17 at 04:48
  • And you did say you failed to find a simpler solution ... – cfr Jan 22 '17 at 04:51
  • So, the real answer is “TikZ is magic and we can't tell which macro will work where. Just don't do it.”? – Hermann Döppes Jan 22 '17 at 04:58
  • 1
    No, but what you do here needs to play by the rules of PGF/TikZ. You need to take account of how it is parsing the input and can't assume that stuff is being parsed simply and directly by TeX/LaTeX, because it is not. This is why things like Babel can cause havoc if the language uses active short-hands and you have to take special precautions e.g. turning short-hands off inside TikZ pictures etc. – cfr Jan 22 '17 at 14:42