2

I have some code that generates some random content. I would like to add the ability to use the last-results instead of generating new random values. The way I thought to do this would be to 'save' the random numbers/results into a persistent location and load them under certain conditions (eg have some optional argument in the command generating the random values that allows you to flag whether you want to use the last results or generate new ones).

I know things like the \label and \ref systems do this, which is why you have to compile twice, so I was thinking about utilizing whatever system is working in the background with them. Unfortunately I've never tinkered with this part of LaTeX and have no idea what it is even called or where to look to find information about it. If anyone could at least point me in the right direction (or tell me it can't realistically be done) I'd appreciate it.

If it matters I typically prefer to work with LaTeX2 or LaTeX, but I have been (slowly) learning LaTeX3 so that's at least plausible as well. Thanks!

  • I would use something like phantom labels and retrieve it with \getrefnumber from refcount for this – user31729 Sep 6 '17 at 16:40
  • This is an interesting idea. Is there a maximum number of labels that can be stored? Some runs of the program could (in theory) require up to a few hundred 'saved' numbers. I know LaTeX doesn't like having a lot of counters, but no idea about labels. – Jason Sep 6 '17 at 16:42
  • If you don't plan to have 100000 labels it should be ok, but in this case storing a property list with the individual saved numbers as one label is perhaps the better approach – user31729 Sep 6 '17 at 16:48
  • Mechanism behind ToC is described in https://tex.stackexchange.com/questions/273098/mimicking-latexs-table-of-contents-functionality/273106#273106, but the \label, \ref approach is the better one, in my point of view if it is done with expandable commands – user31729 Sep 6 '17 at 16:50
3

A way with a phantomlabel, i.e. setting \@currentlabel to the content of the first argument of a macro and applying \label{#2} later on.

The random content is generated with \fpeval{rand()}, in order to retrieve it with possible expansion use \getrefnumber from refcount package.

\documentclass{article}

\usepackage{refcount}
\usepackage{xfp}
\usepackage{xparse}
\makeatletter
\NewDocumentCommand{\saverandom}{+mm}{%
  \protected@edef\@currentlabel{#1}%
  \label{#2}%
}
\makeatother

\begin{document}
\pdfsetrandomseed100
The last value was \getrefnumber{foo}
\saverandom{\fpeval{rand()}}{foo}

However: \fpeval{rand()}

\end{document}

Basically the same version but for more discussion about the \edef and robust commands

\documentclass{article}

\usepackage{refcount}
\usepackage{xfp}
\usepackage{xparse}

\usepackage[most]{tcolorbox}

\DeclareRobustCommand{\foo}[1]{\begin{tcolorbox}[colback=white!60!yellow]#1\end{tcolorbox}}

\newcommand{\fooagain}[1]{\begin{tcolorbox}[colback=white!60!yellow]#1\end{tcolorbox}}

\makeatletter
\NewDocumentCommand{\saverandom}{+mm}{%
  \protected@edef\@currentlabel{#1}%
  \label{#2}%
}
\makeatother

\newcommand{\sometestcontent}{This is a command}

\begin{document}
\pdfsetrandomseed100
The last value was \getrefnumber{foo} or \getrefnumber{fooagain} or \ref{fooagain}
\saverandom{\fpeval{rand()}}{foo}

However: \fpeval{rand()}

\saverandom{Some \foo{A box} stuff}{foostuff}

\saverandom{Some \foo{\sometestcontent} stuff}{foomorestuff}

\saverandom{Some \protect\fooagain{A box} stuff}{fooagain}

\saverandom{Some \protect\fooagain{\sometestcontent} stuff}{fooagainagain}

\end{document}

enter image description here

This provides the .aux file (%%%% comments added by me later on)

\relax 
\providecommand\tcolorbox@label[2]{}
\newlabel{foo}{{0.6812090612411411}{1}}
\newlabel{foostuff}{{Some \foo  {A box} stuff}{1}}
\newlabel{foomorestuff}{{Some \foo  {This is a command} stuff}{1}}%%%% \sometestcontent is expanded, \foo isn't
\newlabel{fooagain}{{Some \fooagain {A box} stuff}{1}}
\newlabel{fooagainagain}{{Some \fooagain {This is a command} stuff}{1}}%%%% \sometestcontent is expanded, but \fooagain isn't because of \protect
  • Are there limitations to what you could save in a \@currentlabel? ie could I use such a phantom label to define an entire text-block, like you would with a (no-argument) macro? – Jason Sep 6 '17 at 21:09
  • @Jason: \@currentlabel is usually defined as \protected@edef, i.e. the content is expanded in order to store the current state. If there are robust commands inside, they will be transported to the .aux file just as such, i.e. \foo will remain \foo and not expanded to its meaning, it will grab the current meaning of \foo at the moment \getrefnumber or \ref is used. This might be useful, but could also 'dangerous' – user31729 Sep 6 '17 at 21:11
  • This is true even if you are using edef? I was under the impression edef fully expands all it's contents before saving the defined macro explicitly in case there is some dynamic definitions at play that might change the edef'ed command's contents. For example, if I had a command \newcommand{\foo}{this is a command} and then did a \protected@edef\@currentlabel{\foo} \label{test} what would be put in the aux file, just \foo, or "this is a command"? If I used \ref{test} would this be replace with \foo (and then expanded) or "this is a command" (directly)? – Jason Sep 6 '17 at 21:24
  • @Jason: an \edef can't expand an robust command inside, but your \foo macro from the command will place this is a command in the .aux file. If you would replace \newcommand by \DeclareRobustCommand it will place \foo, however. – user31729 Sep 6 '17 at 21:30
  • @Jason: If you want to keep a macro from being expanded in an \edef use \protect\foo, for example – user31729 Sep 6 '17 at 21:36

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.