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
|
@Section
@Tag { visibility }
@Title { Nested definitions, body parameters, extend, import, and export }
@Begin
@PP
A definition may contain
nested.def @Index { Nested definitions }
other definitions at the beginning of its body:
@ID @OneRow @Code {
"def @NineSquare"
" right x"
"{"
" def @Three { x |0.2i x |0.2i x }"
""
" @Three /0.2i @Three /0.2i @Three"
"}"
}
A parameter like @Code x may be invoked anywhere within the body of the
symbol it is a parameter of, including within nested definitions. A
nested symbol like @Code "@Three" may be invoked anywhere from the
beginning of its own body to the end of the body of the symbol it is
defined within. So, assuming an appropriate definition of
{@Code "@Box"},
@ID @Code {
"@NineSquare @Box"
}
has result
@ID @Fig {
@NineSquare @Box { 0.2i @Wide 0.2i @High }
}
Nested definitions may themselves contain nested definitions, to
arbitrary depth.
@PP
There are three special features which permit a nested symbol or
parameter to be invoked outside its normal range; that is, outside the
body of the enclosing symbol. The first and simplest of these features
is the {@I {body parameter}},
parameter.body @SubIndex { @Code body parameter }
body.par @Index { @Code body parameter }
an alternative form of right parameter. The Eq equation formatting
package @Cite { $kingston1995lout.user, Chapter 7 } is a classic example
of the use of a body parameter. In outline, it looks like this:
@ID @OneRow @Code {
"export \"+\" sup over"
""
"def @Eq"
" body x"
"{"
" def \"+\" ..."
" def sup ..."
" def over ..."
" ..."
""
" Slope @Font x"
"}"
}
First we list those nested symbols and parameters that we intend to
refer to outside the body of @Code "@Eq" in an @Code export clause,
export @Index { @Code export clause }
preceding the definition as shown. Only exported symbols may be
invoked outside the body of {@Code "@Eq"}. The body parameter is like a
right parameter except that the exported symbols are visible within it:
@ID @Code {
"@Eq { {x sup 2 + y sup 2} over 2 }"
}
calls on the nested definitions of @Code "@Eq" to produce the result
@ID {
@Eq { {x sup 2 + y sup 2} over 2 }
}
The body parameter's value must be enclosed in braces. The term `body
parameter' is a reminder that the value is interpreted as if it was
within the body of the symbol.
@PP
A body parameter may not be exported, and in fact a body parameter may
be invoked only within the body of the enclosing symbol, not within
any nested definitions. For example, @Code "x" above may not be invoked
within {@Code "sup"}. This restriction is needed to avoid the
possibility of recursion, when the actual body parameter invokes an
exported nested definition which invokes the body parameter, etc.
@PP
The second place where exported symbols may be used is in the right
parameter of the @@Open symbol, and following its alternative form,
@@Use (Section {@NumberOf open}).
@PP
Exported nested symbols and parameters may be made visible within
a subsequent definition or macro by preceding it with an @Code import
import @Index { @Code import clause }
clause, like this:
@ID @OneRow @Code {
"import @Eq"
"def pythag { sqrt { x sup 2 + y sup 2 } }"
}
Note however that @Code pythag can only be used with some invocation of
{@Code "@Eq"}: within the body parameter of an invocation of {@Code "@Eq"},
within the right parameter of an {@Code "@Eq&&tag @Open"}, or following
a {@Code "@Use { @Eq ... }"}. There may be several symbols in the
@Code import clause.
@PP
In a similar way to {@Code "import"}, a definition may be preceded
by {@Code "extend"} followed by a symbol name:
@ID @OneRow @Code {
"extend @Eq"
"def pythag { sqrt { x sup 2 + y sup 2 } }"
}
The effect of this is just as though the definition of @Code "pythag"
had occurred directly after the existing definitions within
{@Code "@Eq"}, with {@Code "pythag"} added to {@Code "@Eq"}'s
export list. This is useful for extending the capabilities of a
package of definitions like @Code "@Eq" without modifying its source
file. The essential differences to @Code "import" are that all the
symbols of @Code "@Eq" become visible within {@Code "pythag"}, not
just the exported ones, and only one symbol may follow the
@Code "extend" keyword.
@PP
Actually, more than one symbol may follow {@Code extend}, but this
usage indicates a `path name' of the symbol. For example,
@ID @OneRow @Code {
"extend @DocumentLayout @ReportLayout"
"def @Keywords ..."
}
causes the definition of @Code "@Keywords" to occur directly after
the existing definitions of {@Code "@ReportLayout"}, which itself
lies within {@Code "@DocumentLayout"}.
@PP
A named parameter may also be preceded by an @Code "import" clause.
As usual, the meaning is that the visible local definitions of
the import symbol(s) are visible within the body (the default
value) of the named parameter. But furthermore, those symbols
will be visible within all invocations of the parameter. For
example, suppose we define
@ID @OneRow @Code {
"def @Diag"
" import @Algebra named linewidth { 1p }"
" import @Algebra named dashlength { 2p }"
" ..."
}
Then, if @Code "@Algebra" exports symbols {@Code "+"},
{@Code "-"}, and so on, we may write
@ID @OneRow @Code {
"@Diag"
" linewidth { 1f - 2p }"
" dashlength { 1f + 2p }"
}
using the symbols from {@Code "@Algebra"}. There may be several
symbols after the @Code "import" keyword. All these symbols
share an important restriction: they may not have parameters.
This is necessary because Lout would be unable to determine
suitable values for any such parameters, if they did exist.
@PP
As an exception to the rule just given, a named parameter may
import the symbol it is a parameter of:
@ID @OneRow @Code {
"export @Cell"
"def @Tbl"
" import @Tbl named @Format { ... }"
}
In this example the exported definitions of @Code "@Tbl" (i.e.
{@Code "@Cell"}) will be visible within {@Code "@Format"}. However,
they may only be used in actual parameters, not in the default
value of the named parameter. This is owing to implementation
problems: at the time the default value of {@Code "@Format"} is
read, the exported symbols have not been read and are consequently
not known.
@PP
Since @Code "@Cell" is nested within {@Code "@Tbl"}, the
value of an invocation of @Code "@Cell" may depend on the value
of parameters of {@Code "@Tbl"}. If @Code "@Cell" is used within
an actual {@Code "@Format"} parameter, its value depends on the
value of parameters of the invocation of {@Code "@Tbl"} of which
the {@Code "@Format"} parameter is a part.
@PP
A definition, macro, or named parameter may have several alternative
names, like this:
@ID @Code "macro @CD @CentredDisplay @CenteredDisplay { ... }"
This is useful for abbreviated and alternative spellings, as shown. The
names appear together, and they may subsequently be used interchangeably.
@PP
If one name of a symbol appears in an export or import list, its other
names are automaticaly included as well, and should not also appear
in the list.
@End @Section
|