3

In the The TeX Book, in apendix B, I read

\def\obeyspaces{\catcode`\ =\active}
{\obeyspaces\global\let =\space}
{%
\catcode`\^^M=\active % these lines must end with ‘%’
\gdef\obeylines{\catcode`\^^M=\active \let^^M=\par}%    
\global\let^^M=\par % this is in case ^^M appears in a \write
} 

The \obeylines macro says ‘\let^^M=\par’ instead of ‘\def^^M{\par}’ because the \let technique allows constructions such as ‘\let\par=\cr \obeylines \halign{...}’ in which \cr’s need not be given within the alignment.

But I don't get the suggested point in that comment. Could someone help me?

2
  • In most computer languages, every variable is assigned a location in memory. In others, (like MATLAB) the name can point to any location in memory and frequently changes. \def assigns a token string to a macro name. \let assigns the location of a previously defined token string to a name. The token string will not be changed or deleted until there are no macros linked to it (TeX keeps track). Commented Aug 11, 2021 at 15:41
  • @JohnKormylo I always wondered, what happens internally in TeX when you \let some macro be equal to a primitive and then delete the original primitive?
    – Gaussler
    Commented Aug 17, 2021 at 10:56

1 Answer 1

8

For (some) purposes, a primitive \halign needs to directly "see" the & and \cr tokens that end alignment cells. You can see the effect in LaTeX where some packages grabbing cell contents don't work so well in the last column, which ends with \\ (which is a macro with \cr in its definition) as opposed to other columns that end with & directly.

By using \let as described, the end result is that at the end of line TeX places an active character with meaning the \cr csname, and not an active character with a meaning that is a macro that expands to \cr.

The following example produces two alignments but if you change \iffalse to \iftrue a third attempt using the suggested definition with \def instead of \let is used, which fails.


\def\test#1{[#1]}

\halign{\hfil\test{#}\cr
aaa\cr
bb\cr
c\cr}

{\let\par\cr\obeylines%
\halign{\hfil\test{#}
aaa
bb
c
}}%


\iffalse % this doesn't work
{%
\catcode`\^^M=\active % these lines must end with ‘%’
\gdef\obeylines{\catcode`\^^M=\active \def^^M{\par}}%    
\global\def^^M{\par}% this is in case ^^M appears in a \write
} 

{\let\par\cr\obeylines%
\halign{\hfil\test{#}
aaa
bb
c
}}%

\fi
\bye
2
  • I've certainly hit the \\ problem a few times (in tabular, if I recall), but I don't recall the circumstances (some macro manipulating cell contents). Thanks for the elucidation. Commented Aug 11, 2021 at 14:23
  • If I got, \halign scans its content looking for tips (\cr and &) to define and check its structure. Macros has, in some way, the address of the content that defines it. Using \let to define a macro, the new one has a copy of this specific address where the binding macro points to. By the way, using \def, a new memory is located. So, when \halign scans its content, he can't deal with such indirect reference, accusing a problem. I know that it's a fairy tale... but sounds someway real. I think I got the point. Thank you! Commented Aug 12, 2021 at 0:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .