summaryrefslogtreecommitdiff
path: root/info/digests/texline/no10/victor.tex
blob: bfbe876143e26770c77f8e3dd0218e84f948abe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
\centerline{\bf And now for something completely {\tt\char'134else}}
\smallskip
\noindent
Over the years I have programmed in a number of languages
(this does not include Basic!), and every once in a while
I had occasion to ponder their conceptual differences.
Such reflection need not be a sign of intellectual
maturity, by the way.
I still recall with shame coming back to Lisp after a year
of {\sc Fortran}, and attempting -- futilely! --
to do call-by-reference parameter passing\dots\
 
A remnant of my Algol68 years is the desire to write
code like
\begintt
If something Then a Else b Fi :=5;
\endtt
which to me is superior to, as well as conceptually more
correct than,
\begintt
If something Then a:=5 Else b:=5 Fi;
\endtt
Would such a thing be possible in \TeX?
 
Let the following macros be given.
\begintt
\def\bold#1{{\bf #1}}
\def\slant#1{{\sl #1}}
\def\kill#1{}
\endtt
Now let's make some examples. The first one.
\begintt
\ifnum1>0 \bold \fi {word} \bye
\endtt
The `word' appears in roman type, and the log file doesn't give
any further clue as to what happens.
If you switch on |\tracingmacros|, however, you see that |\bold|
did get an argument: it got the |\fi|!
 
Example number two.
\begintt
\ifnum1>0 \bold
    \else \slant \fi {word} \bye
\endtt
Now `word' is bold but the log file says that
`end occured in group at level~1'.
This is a tricky one.
Ask yourself: which closing brace got lost?
And where did it do so?
Let's just expand: |\bold| got hold of the |\else|,
so in the next step the input to \TeX's
gastro-intestinal tract looks like
\begintt
\ifnum1>0 {\bf \else } \slant \fi
\endtt
and as the condition is true, everything between |\else| and
|\fi| will be skipped, including the closing brace.
Note that we have managed to
throw something to the other side of the |\else|!
 
The next example should be understandable by now:
\begintt
\ifnum1<0 \bold
    \else \kill \fi {word} text \bye
\endtt
this gives `end occured before |\ifnum| was complete'.
 
So, is there no \TeX\ equivalent of that Algol construct?
Well this is a way out:
\begintt
\ifnum1>0 \let\next=\bold
    \else \let\next=\kill \fi
  \next {word} text \bye
\endtt
but, this also works:
\begintt
\ifnum1>0 \expandafter \bold
    \else \expandafter \kill \fi
  {word} text \bye
\endtt
We will have to look at this last one a bit closer.
From the first two examples we know that the lexical expansion
of |\else| and |\fi| is empty, so what would happen in the following
case?
\begintt
\ifnum1>0 \expandafter \bold
    \else {word} \fi {text} \bye
\endtt
It is not so that `expanding away' the else gives `word' as
argument to |\bold|.
 
The following explanation would be imaginable:
maybe \TeX\ skips the `false
text' as soon as it sees the |\else|. This might be possible,
as no expansion is involved in the skipping.
In particular, the |\fi| cannot be the result of a macro
expansion, it really has to be standing there.
We can test that this is indeed the case
with a final example:
\begintt
\def\hello{\message{hello}}
\ifnum1>0 \expandafter \hello
    \else \message{goodbye} \bye
\endtt
Now \TeX\ sees the |\else| before the `hello' message, so it
can start skipping at that very moment.
You can deduce that it does so,
because it doesn't greet you before giving
the error message for the missing |\fi|.
 
All of this means that conditionals in \TeX\ are rather
more complicated than in ordinary programming
languages, but they can be understood once you
realise that: (1)~|\else| and |\fi| are
ordinary tokens; and (2)~for true conditions,
the `false text' is skipped as soon as
the |\else| has been located.

\rightline{\sl Victor Eijkhout}