aboutsummaryrefslogtreecommitdiffstats
path: root/doc/expert/pri_defi
blob: 002db1500348efa3d1db4ebdcf63f4be7b554d50 (plain) (blame)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
@Section
   @Title { Definitions }
   @Tag { definitions }
@Begin
@PP
The features of Lout are very general.  They do not assume that documents
are composed of pages, nor that there are such things as margins and
footnotes, for example.  @I Definitions
definitions. @Index { Definitions }
bridge the gap between Lout's general features and the
special features -- footnotes, equations, pages -- that particular
documents require.  They hold the instr&-uct&-ions for producing these
special features, conveniently packaged ready for use.
@PP
For example, consider the challenge posed by `@TeX', which is the name of
one of Lout's most illustrious rivals @Cite { $knuth1984tex }.  Lout solves it
easily enough, like this:
@ID @Code {
"T{ /0.2fo E }X"
}
but to type this every time @TeX is mentioned would be tedious and
error-prone.  So we place a definition at the beginning of the document:
@ID @Code {
"def  @TeX  {  T{ /0.2fo E }X  }"
}
Now @Code "@TeX" stands for the object following it between
braces, and we may write
@ID @Code {
consider the challenge posed by "`@TeX'", ...
}
as the author did earlier in this paragraph.
@PP
A @I symbol
symbol. @Index Symbol
is a name, like {@Code "@TeX"}, which stands for
something other than itself.  The initial @Code "@" is not compulsory,
but it does make the name stand out clearly.  A @I definition of a symbol
declares a name to be a symbol, and says what the symbol stands for.  The
@I body of a definition
body.of @Index { Body of a definition }
is the part following the name, between the braces.  To @I invoke
invocation @Index { Invocation of a symbol }
a symbol is to make use of it.
@PP
Another expression ripe for packaging in a definition is
@ID @Code {
"@OneRow {  |  -2p @Font n  ^/0.5fk  2  }"
}
which produces @OneRow { | -2p @Font n ^/0.5sk 2 } (see
Chapter {@NumberOf details}).  But this time we would like to be able to write
@ID {
@I object  @Code "@Super"  @I object
}
so that @Code { a "@Super" 2 } would come out as {a @Super 2}, and so
on, for in this way the usefulness of the definition is greatly
increased.  Here is how it is done:
@ID @OneRow @Code {
"def @Super"
"   left x"
"   right y"
"{ @OneRow {  |  -2p @Font y  ^/0.5fk  x  }"
"}"
}
This definition says that @Code "@Super" has two {@I parameters},
parameter @Index Parameter
@Code x and {@Code y}.  When @Code "@Super" is invoked, all occurrences
of @Code x in the body will be replaced by the object just to the left
of {@Code "@Super"}, and all occurrences of @Code y will be replaced by
the object just to the right.  So, for example, the expression
@ID @Code {
"2  @Super  { Slope @Font n }"
}
is equal to
@ID @Code {
"@OneRow {  |  -2p @Font { Slope @Font n }  ^/0.5fk  2  }"
}
and so comes out as {2 @Super {Slope @Font n}}.
@PP
Lout permits definitions to invoke themselves, a peculiarly circular
thing to do which goes by the name of
recursion @Index Recursion
@I recursion.  Here is an example
of a recursive definition:
@ID @Code {
"def  @Leaders  {  ..   @Leaders  }"
}
The usual rule is that the value of an invocation of a symbol is a copy of
the body of the symbol's definition, so the value of @Code "@Leaders" must be
@ID @Code {
"..   @Leaders"
}
But now this rule applies to this new invocation of {@Code "@Leaders"};
substituting its body gives
@ID @Code {
"..   ..   @Leaders"
}
and so on forever.  In order to make this useful,
an invocation of a recursive symbol is replaced by its body only if
sufficient space is available.  So, for example,
@ID @Code {
"4i @Wide { Chapter 7  @Leaders   62 }"
}
has for its result the object
@ID {
4i @Wide { Chapter 7  @Leaders   62 }
}
with Lout checking before each replacement of @Code "@Leaders" by
@OneCol @Code { ".."   "@Leaders" } that the total length afterwards,
including the other words, would not exceed four inches.
@PP
The remaining issue is what happens when Lout decides that it is time to
stop.  The obvious thing to do is to replace the last invocation by an
empty object:
@ID @Code {
"..    ..    ..    ..    ..    ..    ..    ..    {}"
}
As the example shows, this would leave a small trailing space, which
is a major headache.  Lout fixes this
by replacing the last invocation with a different kind of empty object,
called @@Null, whose effect is to make an adjacent concatenation symbol
disappear, preferably one preceding the @@Null.  Thus, when Lout
replaces @Code "@Leaders" by @@Null in the expression
@ID @Code {
"..    ..    ..    ..    ..    ..    ..    ..    @Leaders"
}
the trailing space, which is really a horizontal concatenation symbol,
disappears as well.  This is taken into account when deciding
whether there is room to replace @Code "@Leaders" by its body.
@PP
The remainder of this section is devoted to showing how definitions may
be used to specify the @I {page layout}
page.layout @RawIndex { Page layout }
page.layout.basic @SubIndex { principles of }
of a document.  To begin with,
we can define a page like this:
@ID @OneRow @Code {
"def @Page"
"{"
"    //1i  ||1i"
"    6i @Wide 9.5i @High"
"    { @TextPlace  //1rt  @FootSect }"
"    ||1i  //1i"
"}"
}
Now @Code "@Page" is an eight by
eleven and a half inch object, with one inch margins, a place at the top for
text, and a section at the bottom for footnotes (since @Code "//1rt"
bottom-justifies the following object).  It will be
convenient for us to show the effect of invoking @Code "@Page" like this:
@ID @Code
{ { //0.5ix 8p @Font "@Page" &2m => } &2m
@LittlePage { "@TextPlace" //1rt "@FootSect" }
}
with the invoked symbol appearing to the left of the arrow, and its body to
the right.
@PP
The definition of a vertical list of pages should come as no surprise:
@ID @OneRow @Code {
"def @PageList"
"{"
"    @Page  //  @PageList"
"}"
}
This allows invocations like the following:
@ID @Code @HExpand @HScale {
{ //0.5ix 8p @Font "@PageList" }
||1m { //0.5ix => } ||1m
{        @LittlePage { "@TextPlace" //1rt "@FootSect" }
  //0.2c 8p @Font "@PageList"
}
||1m { //0.5ix => } ||1m
{        @LittlePage { "@TextPlace" //1rt "@FootSect" }
  //     @LittlePage { "@TextPlace" //1rt "@FootSect" }
  //0.2c 8p @Font "@PageList"
}
||1m { //0.5ix => } ||1m
{        @LittlePage { "@TextPlace" //1rt "@FootSect" }
  //     @LittlePage { "@TextPlace" //1rt "@FootSect" }
}
}
setting  @Code "@PageList" to @Code @@Null on the last step.  Any
number of pages can be generated.
@PP
A definition for @Code "@TextPlace" is beyond us at present, since
@Code "@TextPlace" must be replaced by different parts of the text
of the document on different pages.  But we can
define @Code "@FootSect" to be a small space followed by a
horizontal line followed by a list of places where footnotes go:
@ID @OneRow @Code {
"def @FootList         "
"{                     "
"   @FootPlace  //0.3v  @FootList"
"}                     "
"                      "
"def @FootSect"
"{                        "
"   //0.3v 1i @Wide @HLine"
"   //0.3v @FootList      "
"}                        "
}
assuming that @Code "@HLine" will produce a horizontal line of the
indicated width.  With this definition we can generate pages like this:
@ID @Code {
@LittlePage { "@TextPlace"
               //1rt
               "@FootSect"
             }
||2m { //0.5ix => } ||2m
@LittlePage { "@TextPlace"
               //1rt
               @OneRow { 1c @Wide @HLine
                         //0.1c
                         "@FootList"
                       }
             }
||2m { //0.5ix => } ||2m
@LittlePage { "@TextPlace"
               //1rt
               @OneRow { 1c @Wide @HLine
                         //0.1c
                         "@FootPlace"
                         //0.1c
                         "@FootList"
                       }
             }
}
and so on for arbitrarily many footnotes.
@PP
We will see in the next section how invocations of @Code "@PageList",
@Code "@FootSect" and @Code "@FootList" are replaced by their bodies only
when the need to insert text and footnotes obliges Lout to do so;
otherwise the invocations are replaced by @@Null.  In this way, the
right number of pages is made, the small line appears only on pages that
have at least one footnote, and unnecessary concatenation symbols
disappear.
@PP
This approach to page layout is the most original contribution Lout has
made to document formatting.  It is extraordinarily flexible.  Two-column
pages?  Use
@ID @Code {
"{2.8i @Wide @TextPlace}  ||0.4i  {2.8i @Wide @TextPlace}"
}
instead of {@Code "@TextPlace"}.  Footnotes in smaller type?  Use
@Code { -2p "@Font" "@FootPlace" } instead of {@Code "@FootPlace"}.  And
on and on.
@End @Section