TransWikia.com

Alignment tab character inside a starred command within align

TeX - LaTeX Asked by Lawrence Wong on April 24, 2021

Here is a minimal example of what I want to do.

documentclass{article}

usepackage{amsmath}

makeatletter
newcommand{mylinebreak}{@ifstar@mylinebreak@@mylinebreak}
newcommand{@mylinebreak}{&}
newcommand{@@mylinebreak}{&&}
%letmylinebreak@@mylinebreak
makeatother

begin{document}
begin{align*}
 a&=bmylinebreak
  &=c.
end{align*}
end{document}

This gives the error message

! Misplaced alignment tab character &.
@@mylinebreak ->&
                  &
l.16 end{align*}

What is wrong? How can I get this to work?

Curiously, I get no error message if I remove the % or if I use mylinebreak* instead.

I am guessing that the problem can be solved using the tricks involving master/balance counters, but I could not make this work.

2 Answers

You are defining to look ahead for a * (incidentally the standard command already looks ahead for a *) but in doing this it "sees" the & and the next cell starts before the previous row is ended by inserting the original

The definition in amsmath is

defmath@cr{relaxiffalse{fiifnum0=`}fi
  @ifstar{global@eqpen@Mmath@cr@}%
          {global@eqpen
             ifnumdspbrk@lvl <z@ interdisplaylinepenalty
              else -@getpendspbrk@lvl fi
           math@cr@}}
defmath@cr@{new@ifnextchar[math@cr@@{math@cr@@[z@]}}
defmath@cr@@[#1]{ifnum0=`{fi iffalse}fimath@cr@@@
  noalign{vskip#1relax}}

The special relaxiffalse{fiifnum0=`}fi is designed to avoid this issue by preventing the halign template ending a cell at this point.

Note that it is already using @ifstar to define * to prevent a page break at this point.

It is not clear what is the intention of using & as the behaviour of that construct is the same as as the empty cells do not do anything in almost all circumstances.

Correct answer by David Carlisle on April 24, 2021

TL;DR

Simple solution: use a more robust check for the *-variant.

documentclass{article}

usepackage{amsmath}

NewDocumentCommand{mylinebreak}{s}{%
  IfBooleanTF{#1}{&x}{&x&=y}%
}

begin{document}
begin{align*}
 a&=bmylinebreak
  &=c.
 a&=bmylinebreak*
  &=c.
end{align*}
end{document}

enter image description here

I added something in order to better see that the choices are made correctly.

If you're running a version of LaTeX prior to the 2020-10-01 release, you also need usepackage{xparse}.

Analysis of the issue

Let's see what happens: mylinebreak becomes

@ifstar@mylinebreak@@mylinebreak

According to the definition of @ifstar by amsmath

def@ifstar#1#2{new@ifnextchar *{defreserved@a*{#1}reserved@a}{#2}}

the above becomes

new@ifnextchar*{defreserved@a{@mylinebreak}reserved@a}{@@mylinebreak}

Let's see what new@ifnextchar does:

longdefnew@ifnextchar#1#2#3{%
  letreserved@d= #1%
  defreserved@a{#2}defreserved@b{#3}%
  futurelet@let@tokennew@ifnch
}

so the expansions continues as (newlines just for reading convenience)

letreserved@d= *
defreserved@a{defreserved@a*{@mylinebreak}reserved@a}
defreserved@b{@@mylinebreak}
futurelet@let@tokennew@ifnch &

The trailing & comes from the fact that the newline after mylinebreak is ignored during tokenization. Unfortunately, we're in an alignment, so as soon as TeX scans &, it inserts the v part of the template. And, indeed, the error message with a high value of errorcontextlines reads

! Misplaced alignment tab character &.
@@mylinebreak ->&
                  &
<to be read again> 
                   }
<template> }
            $}ifmeasuring@ savefieldlength@ fi set@field hfil endtempl...
<argument>  a&=bmylinebreak &
                              =c. 

and @let@token is set to }. This is confirmed by injecting show@let@token at the beginning of new@ifnch:

@let@token=end-group character }

OK, let's go a step forward: the expansion of new@ifnch yields

ifx@let@tokenreserved@dletreserved@breserved@afireserved@b

In our case, the ifx test returns false, so we remain with

reserved@b}&

and this breaks, because reserved@b becomes @@mylinebreak.

Answered by egreg on April 24, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP