9

I'm trying to save a length in the .aux file, so that it is remembered in the following compilation.

In other words, I'm looking for something like the totcount package, but which works for lengths.

More generally, is there a higher-level mechanism to save values across compilations? Tikz's [remember picture] is great and easy to use, while \protected@write\@auxout feels particularly low-level requires me to mess around with \protected, think about when the file is loaded etc.

Here is my non-working attempt so far.

\documentclass{article}
\makeatletter

\newlength\mylen
\mylen=0pt% Default value

\def\reloadmylen#1{\mylen=#1}

\def\changelen#1{
  \mylen=#1
  \protected@write\@auxout{}{\protect\reloadmylen{\the\mylen}}
}

\makeatother
\begin{document}

\the\mylen% Should print 20pt, but prints 0.0pt.

\changelen{10pt}
\changelen{20pt}

\end{document}
5

\protected@write is used if one wants to write the current value of a macro at the time of page-shipout to an external file.

In the OP's case, the dimen value after use of \changelen shall be stored in \@auxout (\jobname.aux). This can be done immediately and doesn't need to be delayed further, since the last value written out by \changelen is what counts when \jobname.aux is re-read during the second LaTeX run. That is why \protected@write is not the best choice here, but \immediate\write should be preferred.


\documentclass{article}

\newlength\mylen
\mylen=0pt% Default value

\makeatletter    
% persistently sets length register
\def\changelen#1#2{%
  \global#1=#2%
  \immediate\write\@auxout{\global#1=\the#1}%
}
\makeatother

\begin{document}

\the\mylen% Prints 20pt after the second run.

\changelen{\mylen}{10pt}
%\changelen{\mylen}{20pt}
\newlength\otherlen\otherlen=20pt
\changelen{\mylen}{\otherlen} % also works (can be used like `\setlength')

\end{document}
  • Good point. However, that's particularly low-level. \expandafter and \noexpand are particularly hard to get right, aside from the trivial single command and single argument cases. – Georges Dupéron Feb 27 '17 at 13:59
  • Maybe it is also a good idea, for \changelen to accept the name of a length register to make it more versatile. See edit. – AlexG Feb 27 '17 at 14:13
  • @Georges : Hopefully it is not too 'low-level' anymore. – AlexG Feb 28 '17 at 12:58
10

\def\reloadmylen#1{\global\mylen=#1}

  • (I wonder when the system flags this as low quality :-)) – yo' Feb 27 '17 at 13:23
  • Well, that was anticlimatic :) . Thanks! I'll wait a bit if someone suggests a better overall approach (my code is pretty verbose for what should be \newrememberedlength{\mylen}{0pt}). – Georges Dupéron Feb 27 '17 at 13:25
  • Congrats on passing the 35K rep mark!! – Mico Mar 3 '17 at 19:04
2

Depending on the precision you need, you can simply use the totcount package:

\documentclass{article}

\usepackage{printlen}

\usepackage{totcount}
\newtotcounter{mylenght}


\begin{document}

\uselengthunit{mm}\printlength{\totvalue{mylenght}}

\newlength\mylen
\setlength{\mylen}{4.9999999mm}

\setcounter{mylenght}{\mylen}

\end{document}

enter image description here

  • It seems hard to get the value back into a length, however (i.e. using it, not printing it). All variations on \newlength\reloadedlen\expandafter\reloadedlen{\printlength{\totvalue{mylength}}} which I tried seemed to fail. – Georges Dupéron Feb 27 '17 at 13:56
0

You can use totcount with no approximation, using the fact that a length is coerced to an integer if we pass it as the value for a counter.

\documentclass{article}
\usepackage{totcount}

% a `total' counter for saving the value of \mylen
\newtotcounter{savedlength}

% allocate the length    
\newlength\mylen
% set it at begin document (using the last value in the previous run)
% the value had been coerced to an integer, that is, the length in scaled points
\AtBeginDocument{\setlength{\mylen}{\totvalue{savedlength}sp}}

% \changelen sets the value of \mylen, but also stores it in the counter
\newcommand\changelen[1]{%
  \setlength{\mylen}{#1}%
  \setcounter{savedlength}{\mylen}%
}

\begin{document}

\the\mylen

\changelen{10pt}

\the\mylen

\changelen{20pt}

\the\mylen

\end{document}

enter image description here

Note however that doing \changelen in a group will save the value; but you can of course say \setlength when you want to set a temporary value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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