hybrid-glocal.tex /size: 6678 b    last modification: 2023-12-21 09:43
1% language=us
2
3\startcomponent hybrid-glocal
4
5\environment hybrid-environment
6
7\startchapter[title={Glocal assignments}]
8
9Here is a nice puzzle. Say that you do this:
10
11\starttyping
12\def\test{local} \test
13\stoptyping
14
15What will get typeset? Right, you'll get \type {local}. Now take this:
16
17\startbuffer
18\bgroup
19  \def \test {local}[\test]
20  \xdef\test{global}[\test]
21  \def \test {local}[\test]
22\egroup
23                    [\test]
24\stopbuffer
25
26\typebuffer
27
28Will you get:
29
30\starttyping
31[local] [local] [local] [global]
32\stoptyping
33
34or will it be:
35
36\starttyping
37[local] [global] [local] [global]
38\stoptyping
39
40Without knowing \TEX, there are good reasons for getting either of them: is a
41global assignment global only i.e.\ does it reach over the group(s) or is it
42global and local at the same time? The answer is that the global definitions also
43happens to be a local one, so the second line is what we get.
44
45Something similar happens with registers, like counters:
46
47\startbuffer
48\newcount\democount
49\bgroup
50         \democount 1[\the\democount]
51  \global\democount 2[\the\democount]
52         \democount 1[\the\democount]
53\egroup
54                     [\the\democount]
55\stopbuffer
56
57\typebuffer
58
59We get: {\tttf\getbuffer\removeunwantedspaces}, so this is
60consistent with macros. But how about boxes?
61
62\startbuffer
63\bgroup
64         \setbox0\hbox {local}[\copy0:\the\wd0]
65  \global\setbox0\hbox{global}[\copy0:\the\wd0]
66         \setbox0\hbox {local}[\copy0:\the\wd0]
67\egroup
68                              [\copy0:\the\wd0]
69\stopbuffer
70
71\typebuffer
72
73This gives:
74
75\startlines \tttf
76\getbuffer
77\stoplines
78
79Again, this is consistent, so let's do some manipulation:
80
81\startbuffer
82\bgroup
83         \setbox0\hbox{local}         \wd0=6em [\copy0:\the\wd0]
84  \global\setbox0\hbox{global} \global\wd0=5em [\copy0:\the\wd0]
85         \setbox0\hbox{local}         \wd0=6em [\copy0:\the\wd0]
86\egroup
87                                               [\copy0:\the\wd0]
88\stopbuffer
89
90\typebuffer
91
92\startlines \tttf
93\getbuffer
94\stoplines
95
96Right, no surprise here, but \unknown
97
98\startbuffer
99\bgroup
100         \setbox0\hbox{local}  \wd0=6em [\copy0:\the\wd0]
101  \global\setbox0\hbox{global} \wd0=5em [\copy0:\the\wd0]
102         \setbox0\hbox{local}  \wd0=6em [\copy0:\the\wd0]
103\egroup
104                                        [\copy0:\the\wd0]
105\stopbuffer
106
107\typebuffer
108
109See the difference? There is none. The second width assignment is applied to the
110global box.
111
112\startlines \tttf
113\getbuffer
114\stoplines
115
116So how about this then:
117
118\startbuffer
119\bgroup
120         \setbox0\hbox{local}  \wd0=6em [\copy0:\the\wd0]
121  \global\setbox0\hbox{global}          [\copy0:\the\wd0]
122         \setbox0\hbox{local}  \wd0=6em [\copy0:\the\wd0]
123\egroup
124                                        [\copy0:\the\wd0]
125\stopbuffer
126
127\typebuffer
128
129Is this what you expect?
130
131\startlines \tttf
132\getbuffer
133\stoplines
134
135So, in the case of boxes, an assignment to a box dimension is applied to the last
136instance of the register, and the global nature is kind of remembered. Inside a
137group, registers that are accessed are pushed on a stack and the assignments are
138applied to the one on the stack and when no local box is assigned, the one at the
139outer level gets the treatment. You can also say that a global box is unreachable
140once a local instance is used. \footnote {The code that implements \type
141{\global\setbox} actually removes all intermediate boxes.}
142
143\startbuffer
144\setbox0\hbox{outer} [\copy0:\the\wd0]
145\bgroup
146            \wd0=6em [\copy0:\the\wd0]
147\egroup
148                     [\copy0:\the\wd0]
149\stopbuffer
150
151\typebuffer
152
153This gives:
154
155\startlines \tttf
156\getbuffer
157\stoplines
158
159It works as expected when we use local boxes after such an assignment:
160
161\startbuffer
162\setbox0\hbox{outer}           [\copy0:\the\wd0]
163\bgroup
164                      \wd0=6em [\copy0:\the\wd0]
165  \setbox0\hbox{inner (local)} [\copy0:\the\wd0]
166\egroup
167                               [\copy0:\the\wd0]
168\stopbuffer
169
170\typebuffer
171
172This gives:
173
174\startlines \tttf
175\getbuffer
176\stoplines
177
178Interestingly in practice this is natural enough not to get noticed. Also, as the
179\TEX book explicitly mentions that one should not mix local and global usage, not
180many users will do that. For instance the scratch registers 0, 2, 4, 6 and 8 are
181often used locally while 1, 3, 5, 7 and 9 are supposedly used global. The
182argument for doing this is that it does not lead to unwanted stack build-up, but
183the last examples given here provide another good reason. Actually, global
184assignments happen seldom in macro packages, at least compared to local ones.
185
186In \LUATEX\ we can also access boxes at the \LUA\ end. We can for instance change
187the width as follows:
188
189\startbuffer
190\bgroup
191         \setbox0\hbox{local}
192         \ctxlua{tex.box[0].width = tex.sp("6em")} [\copy0:\the\wd0]
193  \global\setbox0\hbox{global}
194         \ctxlua{tex.box[0].width = tex.sp("5em")} [\copy0:\the\wd0]
195         \setbox0\hbox{local}
196         \ctxlua{tex.box[0].width = tex.sp("6em")} [\copy0:\the\wd0]
197\egroup
198                                                   [\copy0:\the\wd0]
199\stopbuffer
200
201\typebuffer
202
203This is consistent with the \TEX\ end:
204
205\startlines \tttf
206\getbuffer
207\stoplines
208
209This is also true for:
210
211\startbuffer
212\bgroup
213         \setbox0\hbox{local}
214         \ctxlua{tex.box[0].width = tex.sp("6em")} [\copy0:\the\wd0]
215  \global\setbox0\hbox{global}                     [\copy0:\the\wd0]
216         \setbox0\hbox{local}
217         \ctxlua{tex.box[0].width = tex.sp("6em")} [\copy0:\the\wd0]
218\egroup
219                                                   [\copy0:\the\wd0]
220\stopbuffer
221
222\typebuffer
223
224Which gives:
225
226\startlines \tttf
227\getbuffer
228\stoplines
229
230The fact that a \type {\global} prefix is not needed for a global assignment at
231the \TEX\ end means that we don't need a special function at the \LUA\ end for
232assigning the width of a box. You won't miss it.
233
234There is one catch when coding at the \TEX\ end. Imagine this:
235
236\startbuffer
237\setbox0\hbox{local} [\copy0:\the\wd0]
238\bgroup
239  \wd0=6em           [\copy0:\the\wd0]
240\egroup
241                     [\copy0:\the\wd0]
242\stopbuffer
243
244\typebuffer
245
246In sync with what we told you will get:
247
248\startlines \tttf
249\getbuffer
250\stoplines
251
252However, this does not look that intuitive as the following:
253
254\startbuffer
255\setbox0\hbox{local} [\copy0:\the\wd0]
256\bgroup
257  \global\wd0=6em    [\copy0:\the\wd0]
258\egroup
259                     [\copy0:\the\wd0]
260\stopbuffer
261
262Here the global is redundant but it looks quite okay to put it there if only to
263avoid confusion. \footnote {I finally decided to remove some of the \type
264{\global} prefixes in my older code, but I must admit that I sometimes felt
265reluctant when doing it, so I kept a few.}
266
267\stopchapter
268
269\stopcomponent
270