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.

Often I have separate .tikz files, which may contain stuff like \newlength{\mytmplen}; and given I'm not very original with names, the same statement ends up in multiple such files. Which turns out to be a problem, if I want to include all those files in a single .tex document -- then upon the second \newlength with the same argument, the compilation process would stop with:

! LaTeX Error: Command \mytmplen already defined.
               Or name \end... illegal, see p.192 of the manual.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.30 \newlength{\mytmplen}

? 

So, I thought of devising a new newlength command, which would define the new length if it doesn't exist; but it would simply typeout a message, and go on if it does exist.

Obviously, I'd have to have a method to check if a command exists; and possibly a method to obtain the command name (e.g. mytmplen) from the command token (e.g. \mytmplen). So far, I found these posts relevant:

I will be posting my solution as answer below; of course, corrections or alternative methods for solving this would be much appreciated!

share|improve this question

3 Answers 3

up vote 5 down vote accepted

Your answer appears to work. A simpler method might consist of first \let-ting the length variable in question to \relax and then applying \newlength to it. Put differently, if you can't remember if a certain macro name has been used before to denote a length parameter (or anything else, really!) and if you're comfortable with (re)using it anyway, you can first \let it to \relax and then issue a \newlength directive.

\documentclass{article}
\begin{document}

\newlength\mytmplen
\setlength\mytmplen{10pt}
\the\mytmplen

\let\mytmplen\relax % let \mytmplen to \relax

\newlength\mytmplen % now it's safe to "re-issue" it as a length 
\setlength\mytmplen{20pt}
\the\mytmplen

\end{document}

enter image description here

share|improve this answer
    
Many thanks for that, @Mico - that is indeed a much simpler approach. Cheers! –  sdaau Jun 15 at 16:06
2  
@sdaau: Until the lengths registers run out. They are a limited resource. –  Heiko Oberdiek Jun 15 at 16:57
    
@HeikoOberdiek - Is there a problem with running out of length registers if the same few ones get re-used over and over? –  Mico Jun 15 at 18:07
    
@Mico: TeX has 256 at most, many of them already in use. With e-TeX 32768 are available, but package etex should be used to make them available. –  Heiko Oberdiek Jun 15 at 18:40
    
@HeikoOberdiek - I guess my question is trying to get at a different issue: Is there a risk of running out of registers if the same macro name, say \mytmplen, is repeatedly first \let to \relax and then reissued as a length register via \newlength? –  Mico Jun 15 at 18:46

Here is a \providelength command that will define a new length if not already defined, but also checks whether the command passed as argument has been defined with \newlength, in order to issue an error message if you try to use, say, \providelength{\textit}.

\documentclass{article}

\makeatletter
\newcommand{\providelength}[1]{%
  \@ifundefined{\expandafter\@gobble\string#1}
   {% if #1 is undefined, do \newlength
    \typeout{\string\providelength: making new length \string#1}%
    \newlength{#1}%
   }
   {% else check whether #1 is actually a length
    \sdaau@checkforlength{#1}%
   }%
}

\newcommand{\sdaau@checkforlength}[1]{%
  % get the first five characters from \meaning#1
  \edef\sdaau@temp{\expandafter\sdaau@getfive\meaning#1TTTTT$}%
  % compare with the string "\skip"
  \ifx\sdaau@temp\sdaau@skipstring
    \typeout{\string\providelength: \string#1 already a length}%
  \else
    \@latex@error
      {\string#1 illegal in \string\providelength}
      {\string#1 is defined, but not with \string\newlength}%
  \fi
}
\def\sdaau@getfive#1#2#3#4#5#6${#1#2#3#4#5}
\edef\sdaau@skipstring{\string\skip}
\makeatother

\begin{document}

\providelength{\foo}
\providelength{\foo}
\providelength{\textit}

\stop

Here is the terminal output:

\providelength: making new length \foo
\providelength: \foo already a length

! LaTeX Error: \textit illegal in \providelength.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.31 \providelength{\textit}

? h
\textit is defined, but not with \newlength
? 
share|improve this answer
    
Many thanks for that, @egreg - good to have that error checking facility; cheers! –  sdaau Jun 15 at 16:27

Ok, so first I looked up the definitions of \newlength and further using texdef:

$ texdef -t latex \newlength

\newlength:
macro:#1->\@ifdefinable #1{\newskip #1}

$ texdef -t latex \@ifdefinable

\@ifdefinable:
\long macro:#1#2->\edef \reserved@a {\expandafter \@gobble \string #1}\@ifundefined \reserved@a {\edef \reserved@b {\expandafter \@carcube \reserved@a xxx\@nil }\ifx \reserved@b \@qend \@notdefinable \else \ifx \reserved@a \@qrelax \@notdefinable \else #2\fi \fi }\@notdefinable 

$ texdef -t latex \@ifundefined

\@ifundefined:
macro:#1->\expandafter \ifx \csname #1\endcsname \relax \expandafter \@firstoftwo \else \expandafter \@secondoftwo \fi 

So, apparently, one can get the command name from the command token, by using the stanza:

\edef\reserved@a{\expandafter\@gobble\string#1} 

... and then the name in \reserved@a (without the backslash) can be used in macros that check for macro existence by command name.

Using those definitions, I've put together this code for a reusable newlength command, called \nnewlength:

\documentclass{article}

\makeatletter
\def\nnewlength#1{%
  \edef\reserved@a{\expandafter\@gobble\string#1} %
  \@ifundefined\reserved@a{%
    \edef\reserved@b{\expandafter\@carcube\reserved@a xxx\@nil} %
    \ifx\reserved@b\@qend %
      \typeout{  -- Not definable (1, \reserved@a): #1} %\@notdefinable %
    \else %
      \ifx\reserved@a\@qrelax %
        \typeout{  -- Not definable (2, \reserved@a): #1} %\@notdefinable %
      \else %
        \typeout{  -- Making newskip: #1}
        \newskip#1%
      \fi %
    \fi %
  }%
  {\typeout{  -- Not definable (E, \reserved@a): #1}} %\@notdefinable%
}
\makeatother

\typeout{1st pass...}
\nnewlength{\mytmplen}
\typeout{2nd pass...}
\nnewlength{\mytmplen}

\begin{document}

\typeout{3rd pass...}
\nnewlength{\mytmplen}

\end{document}

The output is:

This is pdfTeX, Version 3.1415926-2.3-1.40.12 (TeX Live 2011)
...
1st pass...
 -- Making newskip: \mytmplen 
2nd pass...
 -- Not definable (E, mytmplen): \mytmplen 
(./test.aux)
3rd pass...
 -- Not definable (E, mytmplen): \mytmplen 
(./test.aux) )
No pages of output.
Transcript written on test.log.
share|improve this answer

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.