When is it good practice to use \unskip

One sees in source2e the command \unskip used in various places. My understanding in general terms is that the macro is the equivalent of \ignorespacesbehind.

Where would it be recommended to use \unskip?

MWE for experimentation:

\documentclass{article}
\usepackage{lipsum}
\begin{document}
\lipsum[1]
\def\test{\leavevmode \unskip test  }
\def\testa{\leavevmode test\ignorespaces  }

\test testing  \test

\testa testing  \testa test
\end{document}

-
In the first occurrence of \test, \unskip does nothing, because no skip is there; in the second it removes the space after testing (two spaces are normalized to one space token). The \ignorespaces in the two occurrences of \testa does nothing, because no space token is found. –  egreg Mar 24 '13 at 12:26
@egreg Sharp eye:) –  Yiannis Lazarides Mar 24 '13 at 12:56

In addition to @Josephs's points, things to be aware of:

• \unskip acts on horizontal and vertical space, so it will remove vertical space if used between paragraphs.

• Unlike \ignorespaces which affects the conversion between input characters and tokens, \unskip works on the actual lists inside boxes, after all tokenisation and commands have been executed.

• \unskip can not be used in outer vertical mode: Once an item has been added to the main vertical list of a page it can not be removed. So while in a minipage you can remove preceding vertical space with \unskip, on the main page you have to use \vskip-\lastskip to back up over the previous skip rather than actually removing it. This leaves breakable glue so you may also need to inject some \penalties to prevent page breaking.

Consider:

\documentclass{article}

\showoutput
\begin{document}

\setbox0\vbox{

\hbox{g}

\vskip 10pt

\hbox{b}
}

\showbox0

\setbox2\vbox{

\hbox{g}

\vskip 10pt

\unskip\nobreak\hbox{b}
}

\showbox2

\setbox4\vbox{

\hbox{g}

\vskip 10pt

\vskip-\lastskip\nobreak\hbox{b}
}

\showbox2

\hbox{g}

\vskip 10pt

\unskip\nobreak\hbox{b}

\stop


Box 0 is

\vbox(26.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\glue 10.0
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b


But suppose (as in box 2) That the code adding b needs to remove space above, it could use \unskip which literally removes it, resulting in

\vbox(16.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\penalty 10000
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b


If instead of removing it, negative space is added to compensate as n box 4 then you get

\vbox(16.30554+0.0)x5.55557
.\hbox(4.30554+1.94444)x5.00002
..\OT1/cmr/m/n/10 g
.\glue 10.0
.\glue -10.0
.\penalty 10000
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x5.55557
..\OT1/cmr/m/n/10 b


This looks the same but if the penalty was not 10000 then it would be a feasible breakpoint at that position, which means that if the list was unboxed the end of the first part would have depth 0 rather than the depth of g which can have subtle (or not so subtle) affects on positioning that are hard to correct (or at least hard to remember to correct).

So the issues surrounding \unskip are a lot simpler than the vskip-\lastskip combination, however if you are not in a box, you don't have a choice, as the last version on the main page produces:

! You can't use \unskip' in vertical mode.
l.46 \unskip

-
David, will you please expand a bit on the \vskip-\lastskip and what sort of penalties one has to add? –  Yiannis Lazarides Mar 24 '13 at 11:27
@YiannisLazarides I feared you'd ask that (see also Marco's follow on question trouble is the penalties depend on the context (and in general you can't add them) I'll try to add something coherent in a bit –  David Carlisle Mar 24 '13 at 11:38
@YiannisLazarides some examples added. –  David Carlisle Mar 24 '13 at 12:17

The \unskip primitive will remove the last skip from the current list, which includes the common case of a space at the start of some text. Thus \unskip is used where you want to allow some flexibility in the input syntax. For example, it's used in some of the centring code to avoid a space at the start of a line messing up the alignment.

Important notes:

• \unskip will remove only the last skip, so \space\space\unskip will still have one space present.

• \unskip does not remove kerns, so \space\kern0pt\unskip will not remove the space: this may used deliberately to avoid loosing 'required' spaces.

-
What does the following code do: \space\space\unskip\unskip? Will it gobble both \space? –  Marco Daniel Mar 24 '13 at 10:12
@MarcoDaniel effectively yes (although it works on the glue items in the list, not on the \space tokens) –  David Carlisle Mar 24 '13 at 10:17
@DavidCarlisle: What does "list" mean in this contents? How can I imagine this list? Sorry but this is an interesting topic and I am not familiar with ;-) –  Marco Daniel Mar 24 '13 at 10:19
@MarcoDaniel I was just wondering about explaining the character/token/list distinction in the "what is a token" question asked this morning but it doesn't really fit there either. Can't really fit it in a comment I mean what you get in the log if you add \showoutput` to your document. (perhaps a new question is called for, but It might be a duplicate if I see a link I'll add it here) –  David Carlisle Mar 24 '13 at 10:23