2

In order to use & inside align I applied this great answer https://tex.stackexchange.com/a/619983/116348, which basically sets & as active using:

\ExplSyntaxOn
\NewDocumentCommand{\zx}{O{}+m}{%
  \tl_rescan:nn { \char_set_catcode_active:N \& } { \begin{mytikzcd}[#1] #2 \end{mytikzcd} }
}
\ExplSyntaxOff

Unfortunately, I don't know why, but when this code is wrapped into an align, it is evaluated twice (and if the tikz picture takes a lot of time to evaluate... then the twice is multiplied by 2).

I understand that align may parse the token twice, but I'm surprise that the token are actually evaluated twice. Any idea if it's possible to evaluate it only a single time, or if it's a fundamental issue?

MWE

$ pdflatex twice.tex | grep XXX
XXX No align:
XXX>>Called...
XXX With align:
XXX>>Called...
XXX>>Called...
XXX End
\documentclass[]{article}
\usepackage{amsmath}
\usepackage{tikz-cd}

\usepackage{lipsum}

\ExplSyntaxOn \NewDocumentCommand{\zx}{O{}+m}{% \message{XXX >> Called...^^J}% \tl_rescan:nn { \char_set_catcode_active:N & } { \begin{tikzcd}[#1] #2 \end{tikzcd} } } \ExplSyntaxOff

\begin{document}

\message{^^JXXX No align:^^J} \zx{A}

\message{XXX With align:^^J} In align: \begin{align} \zx{A} \end{align}

\message{XXX End^^J} \end{document}

tobiasBora
  • 8,684
  • And the problem is? Essentially everything is evaluated twice in an align. – egreg Feb 08 '22 at 16:08
  • @egreg Well, the problem is that if a document takes 10mn to build before, now it takes 20mn. Oh really, you mean even with a normal command? And there is no solution around that? – tobiasBora Feb 08 '22 at 16:09
  • 1
    Sorry? What do you mean? What's *inside* align gets evaluated twice, not everything in the document. And one *needs* this double evaluation. – egreg Feb 08 '22 at 16:10
  • Sure, but if all the parts that takes a lot of time to compile are inside the align, then the time can be quite long. And this is my case as tikz-external takes like one second to evaluate, if I've only 60 symbols in my paper, then the paper already takes 1mn to compile, which gives 2mn when used inside align environment. And 60 symbols is not a lot. But I didn't know it was needed to evaluate twice, that's true even normal macro get evaluated twice. What's the reason for that? I guess align could avoid that by using boxes or similar, no? – tobiasBora Feb 08 '22 at 16:17
  • 1
    align typesets its contents twice, the first time for measuring and the second time to actually print stuff. In order to prevent code from being duplicated, amsmath provides the conditional \ifmeasuring@ see e.g. https://tex.stackexchange.com/q/105836/82917 – campa Feb 08 '22 at 16:17
  • 1
    @tobiasBora If you have new ideas on how to accomplish the job of align you're welcome to propose them on the GitHub site. Since it has been doing so for more than a quarter of a century… – egreg Feb 08 '22 at 16:20
  • @campa interesting, thanks! I guess I could use \ifmeasuring@ to build the picture and save it in a box, and then re-insert it when \ifmeasuring@ is false... But then I'm not sure how to use properly boxes for that, as I need a way to garbage collect the boxes, without reusing boxes that are already used by other boxes I guess... It's maybe a bit too much work for the benefit. – tobiasBora Feb 08 '22 at 16:21
  • @egreg Well the idea would maybe (I say maybe because I know nothing about the internal of align, and I know how TeX can be technical to use) to save the result in boxes and use the boxes to compute the size of the box. But I guess changing align now would certainly break thousands of other packages, and it may not be easy to program that in (La)TeX. Anyway, thanks a lot, I guess I got my answer. – tobiasBora Feb 08 '22 at 16:27
  • just do the tikz into a \sbox\mybox before the alignment the \usebox\mybox so you just unpack the box twice which is essentially free. – David Carlisle Feb 08 '22 at 16:36
  • @DavidCarlisle Thanks. The only problem of this solution is that it is more cumbersome to use as a user since they need to create multiple boxes before the align. – tobiasBora Feb 08 '22 at 16:42
  • 1
    compared to the effort of using tikz, the effort of moving it up a few lines before the \begin{align} seems rather insignificant to me. – David Carlisle Feb 08 '22 at 16:45

1 Answers1

3

align is always evaluated twice, (other enviornments such as tabularx may be evaluated many times) If you have an expensive construct you can save it in a box so it is only executed once:

\documentclass[]{article}
\usepackage{amsmath}
\usepackage{tikz-cd}

\usepackage{lipsum} \newbox\zz \ExplSyntaxOn \NewDocumentCommand{\zx}{O{}+m}{% \message{XXX >> Called...^^J}% \tl_rescan:nn { \char_set_catcode_active:N & } { \begin{tikzcd}[#1] #2 \end{tikzcd} } } \ExplSyntaxOff

\begin{document}

\message{^^JXXX No align:^^J} \zx{A}

\message{XXX With align:^^J} \sbox\zz{\zx{A}} In align: \begin{align} \usebox\zz \end{align}

\message{XXX End^^J} \end{document}

Produces a log:

XXX No align:
XXX>>Called...
XXX With align:
XXX>>Called...
XXX End
David Carlisle
  • 757,742
  • Thanks (I'll continue here the discussion started in comments). For sure it's easier to do than using tikz, but in my case I wrap tikz to create simple statements like \zx{\zxZ{\alpha} \rar & \zxX{\beta}}, so the final expressions are usually quite short to type and easy to use, but there are many of them (like in my thesis I use it 300 times, and still my thesis uses this only in one or two chapters). So saving 300 creation of boxes is still interesting ^^' The documentation of the library has 260 ocurences https://raw.githubusercontent.com/leo-colisson/zx-calculus/main/doc/zx-calculus.pdf – tobiasBora Feb 08 '22 at 16:55
  • @tobiasBora well don't blame the messenger:-) align is evaluated twice so you need to move the code out of align or evaluate it twice. but how often do you really need to process your entire thesis? if you mean you use the same tikz cd 300 times you should definitely save it in a box. – David Carlisle Feb 08 '22 at 17:05
  • Oh, I don't blame anyone (especially not you, you helped me so many times), I'm really grateful for the help ^^ Sure, usually I don't compile my thesis completely, but I have other libraries that forces me to compile it multiple times until it reaches the final version (like I need to run 2 times latexmk), so if I want to check the final result of the thesis I need like 10-15mn to compile it. Anyway, I guess I can live with that, thanks! But LaTeX really teaches that in life you have to do compromises :-P – tobiasBora Feb 08 '22 at 17:13
  • 3
    @tobiasBora my thesis was done on a typewriter, it took a lot more than 10-15min per page, with no going back, so I have no sympathy:-) – David Carlisle Feb 08 '22 at 17:23
  • Oh my god, I do have sympathy to you ^^' Now I understand why LaTeX is made like that, the creators wanted to be sure that people having access to computers would not get rid of all sufferings they had at their time! – tobiasBora Feb 08 '22 at 17:29
  • 2
    It is indeed funny to see a generation that has no clue on life before the widespread use computers for anything other than scientific calculation. I personally find the demonstration of a slide rule to elicit some of the most flabbergasted reactions, which I relish. – Steven B. Segletes Feb 09 '22 at 00:45