-
-
Notifications
You must be signed in to change notification settings - Fork 655
/
printer.scrbl
644 lines (532 loc) · 31.6 KB
/
printer.scrbl
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
#lang scribble/doc
@(require scribble/bnf "mz.rkt")
@title[#:tag "printing" #:style 'quiet]{The Printer}
The Racket printer supports three modes:
@itemlist[
@item{@racket[write] mode prints core datatypes in such a way that
using @racket[read] on the output produces a value that is
@racket[equal?] to the printed value;}
@item{@racket[display] mode prints core datatypes in a more
``end-user'' style rather than ``programmer'' style; for
example, a string @racket[display]s as its content characters
without surrounding @litchar{"}s or escapes;}
@item{@racket[print] mode by default---when
@racket[print-as-expression] is @racket[#t]---prints most
datatypes in such a way that evaluating the output as an
expression produces a value that is @racket[equal?] to the
printed value; when @racket[print-as-expression] is set to
@racket[#f], then @racket[print] mode is like @racket[write]
mode.}
]
In @racket[print] mode when @racket[print-as-expression] is
@racket[#t] (as is the default), a value prints at a @deftech{quoting
depth} of either @racket[0] (unquoted) or @racket[1] (quoted). The
initial quoting depth is accepted as an optional argument by
@racket[print], and printing of some compound datatypes adjusts the
print depth for component values. For example, when a list is printed
at quoting depth @racket[0] and all of its elements are
@deftech{quotable}, the list is printed with a @litchar{'} prefix, and
the list's elements are printed at quoting depth @racket[1].
When the @racket[print-graph] parameter is set to @racket[#t], then
the printer first scans an object to detect cycles. The scan traverses
the components of pairs, mutable pairs, vectors, boxes (when
@racket[print-box] is @racket[#t]), hash tables (when
@racket[print-hash-table] is @racket[#t] and when key are held strongly), fields of structures
exposed by @racket[struct->vector] (when @racket[print-struct] is
@racket[#t]), and fields of structures exposed by printing when the
structure's type has the @racket[prop:custom-write] property. If
@racket[print-graph] is @racket[#t], then this information is used to
print sharing through graph definitions and references (see
@secref["parse-graph"]). If a cycle is detected in the initial scan,
then @racket[print-graph] is effectively set to @racket[#t]
automatically.
With the exception of displaying @tech{byte strings}, printing is defined in
terms of Unicode characters; see @secref["ports"] for information
on how a character stream is written to a port's underlying byte
stream.
@section[#:tag "print-symbol"]{Printing Symbols}
@tech{Symbols} containing spaces or special characters @racket[write] using
escaping @litchar{\} and quoting @litchar{|}s. When the
@racket[read-case-sensitive] parameter is set to @racket[#f], then
symbols containing uppercase characters also use escaping
@litchar{\} and quoting @litchar{|}s. In addition, symbols are
quoted with @litchar{|}s or leading @litchar{\} when they would
otherwise print the same as a numerical constant or as a delimited
@litchar{.} (when @racket[read-accept-dot] is @racket[#t]).
When @racket[read-accept-bar-quote] is @racket[#t], @litchar{|}s are
used in printing when one @litchar{|} at the beginning and one
@litchar{|} at the end suffice to correctly print the
symbol. Otherwise, @litchar{\}s are always used to escape special
characters, instead of quoting them with @litchar{|}s.
When @racket[read-accept-bar-quote] is @racket[#f], then @litchar{|}
is not treated as a special character. The following are always
special characters:
@t{
@hspace[2] @litchar{(} @litchar{)} @litchar{[} @litchar{]}
@litchar["{"] @litchar["}"]
@litchar{"} @litchar{,} @litchar{'} @litchar{`}
@litchar{;} @litchar{\}
}
In addition, @litchar{#} is a special character when it appears at the
beginning of the symbol, and when it is not followed by @litchar{%}.
Symbols @racket[display] without escaping or quoting special
characters. That is, the display form of a symbol is the same as the
display form of @racket[symbol->string] applied to the symbol.
Symbols @racket[print] the same as they @racket[write], unless
@racket[print-as-expression] is set to @racket[#t] (as is the default) and the current
@tech{quoting depth} is @racket[0]. In that case, the symbol's
@racket[print]ed form is prefixed with @litchar{'}. For the purposes
of printing enclosing datatypes, a symbol is @tech{quotable}.
@section[#:tag "print-number"]{Printing Numbers}
A @tech{number} prints the same way in @racket[write], @racket[display], and
@racket[print] modes. For the purposes of printing enclosing
datatypes, a number is @tech{quotable}.
A @tech{complex number} that is not a @tech{real number} always prints
as @nonterm{m}@litchar{+}@nonterm{n}@litchar{i} or
@nonterm{m}@litchar{-}@nonterm{n}@litchar{i}, where @nonterm{m} and
@nonterm{n} (for a non-negative imaginary part) or
@litchar{-}@nonterm{n} (for a negative imaginary part) are the printed
forms of its real and imaginary parts, respectively.
An exact @racket[0] prints as @litchar{0}. A positive, exact
@tech{integer} prints as a sequence of digits that does not start with
@litchar{0}. A positive, exact, real, non-integer number prints as
@nonterm{m}@litchar{/}@nonterm{n}, where @nonterm{m} and @nonterm{n}
are the printed forms of the number's numerator and denominator (as
determined by @racket[numerator] and @racket[denominator]). A negative
@tech{exact number} prints with a @litchar{-} prefix on the printed
form of the number's exact negation. When printing a number as
hexadecimal (e.g., via @racket[number->string]), digits @litchar{a}
though @litchar{f} are printed in lowercase. A @litchar{#e} or radix
marker such as @litchar{#d} @emph{does not} prefix the number.
A double-precision @tech{inexact number} (i.e., a @tech{flonum}) that
is a @tech{rational number} prints with either a @litchar{.} decimal
point, an @litchar{e} exponent marker and non-zero exponent, or both.
The form is selected to keep the output short, with
the constraint that reading the printed form back in produces an
@racket[equal?] number. A @litchar{#i} @emph{does not} prefix the
number, and @litchar{#} is never used in place of a digit. A
@litchar{+} does not prefix a positive number, but a @litchar{+} or
@litchar{-} is printed before the exponent if @litchar{e} is present.
Positive infinity prints as @litchar{+inf.0}, negative infinity prints
as @litchar{-inf.0}, and not-a-number prints as @litchar{+nan.0}.
A single-precision @tech{inexact number} that is a @tech{rational
number} prints like a double-precision number, but always with an
exponent, using @litchar{f} in place of @litchar{e} to indicate the
number's precision; if the number would otherwise print without an
exponent, @litchar{0} (with no @litchar{+}) is printed as the exponent
part. Single-precision positive infinity prints as
@litchar{+inf.f}, negative infinity prints as @litchar{-inf.f}, and
not-a-number prints as @litchar{+nan.f}.
@section[#:tag "print-extflonum"]{Printing Extflonums}
An @tech{extflonum} prints the same way in @racket[write],
@racket[display], and @racket[print] modes. For the purposes of
printing enclosing datatypes, an extflonum is @tech{quotable}.
An extflonum prints in the same way a single-precision inexact number
(see @secref["print-number"]), but always with a @litchar{t} or
@litchar{T} exponent marker or as a suffix for @litchar{+inf.t}, @litchar{-inf.t},
or @litchar{+nan.t}. When
extflonum operations are supported, printing always uses lowercase
@litchar{t}; when extflonum operations are not supported, an
extflonum prints the same as its reader (see @secref["reader"])
source, since reading is the only way to produce an extflonum.
@section[#:tag "print-booleans"]{Printing Booleans}
The @tech{boolean} constant @racket[#t] prints as @litchar{#true} or @litchar{#t} in
all modes (@racket[display], @racket[write], and @racket[print]),
depending on the value of @racket[print-boolean-long-form], and the
constant @racket[#f] prints as @litchar{#false} or @litchar{#f}. For
the purposes of printing enclosing datatypes, a symbol is
@tech{quotable}.
@section[#:tag "print-pairs"]{Printing Pairs and Lists}
In @racket[write] and @racket[display] modes, an empty @tech{list} prints as
@litchar{()}. A @tech{pair} normally prints starting with @litchar{(}
followed by the printed form of its @racket[car]. The rest of the
printed form depends on the @racket[cdr]:
@itemize[
@item{If the @racket[cdr] is a pair or the empty list, then the
printed form of the pair completes with the printed form of the
@racket[cdr], except that the leading @litchar{(} in the
@racket[cdr]'s printed form is omitted.}
@item{Otherwise, the printed for of the pair continues with a space,
@litchar{.}, another space, the printed form of the
@racket[cdr], and a @litchar{)}.}
]
If @racket[print-reader-abbreviations] is set to @racket[#t], then
pair printing in @racket[write] mode is adjusted in the case of a pair
that starts a two-element list whose first element is @racket['quote],
@racket['quasiquote], @racket['unquote], @racket['unquote-splicing],
@racket['syntax], @racket['quasisyntax], @racket['unsyntax], or
@racket['unsyntax-splicing]. In that case, the pair is printed with
the corresponding reader syntax: @litchar{'}, @litchar{`},
@litchar{,}, @litchar[",@"], @litchar{#'}, @litchar{#`}, @litchar{#,},
or @litchar["#,@"], respectively. After the reader syntax, the second
element of the list is printed. When the list is a tail of an
enclosing list, the tail is printed after a @litchar{.} in the
enclosing list (after which the reader abbreviations work), instead of
including the tail as two elements of the enclosing list. If the
reader syntax @litchar{,} or @litchar{#,} is followed by a symbol
that prints with a leading @litchar["@"], then the printer adds an
extra space before the @litchar["@"].
The printed form of a pair is the same in both @racket[write] and
@racket[display] modes, except as the printed form of the pair's
@racket[car] and @racket[cdr] vary with the mode. The @racket[print]
form is also the same if @racket[print-as-expression] is @racket[#f]
or the quoting depth is @racket[1].
For @racket[print] mode when @racket[print-as-expression] is
@racket[#t] and the @tech{quoting depth} is @racket[0], then the empty
list prints as @litchar{'()}. For a pair whose @racket[car] and
@racket[cdr] are @tech{quotable}, the pair prints in @racket[write]
mode but with a @litchar{'} prefix; the pair's content is printed with
@tech{quoting depth} @racket[1]. Otherwise, when the @racket[car] or
@racket[cdr] is not @tech{quotable}, then pair prints with either
@litchar{cons} (when the @racket[cdr] is not a pair), @litchar{list}
(when the pair is a list), or @litchar{list*} (otherwise) after the
opening @litchar{(}, any @litchar{.} that would otherwise be printed
is suppressed, and the pair content is printed at @tech{quoting depth}
@racket[0]. In all cases, when @racket[print-as-expression] is
@racket[#t] for @racket[print] mode, then the value of
@racket[print-reader-abbreviations] is ignored and reader
abbreviations are always used for lists printed at @tech{quoting
depth} @racket[1].
By default, mutable pairs (as created with @racket[mcons]) print the
same as pairs for @racket[write] and @racket[display], except that
@litchar["{"] and @litchar["}"] are used instead of @litchar{(} and
@litchar{)}. Note that the reader treats @litchar["{"]...@litchar["}"]
and @litchar{(}...@litchar{)} equivalently on input, creating
immutable pairs in both cases. Mutable pairs in @racket[print] mode with
@racket[print-as-expression] as @racket[#f] or a @tech{quoting depth}
of @racket[1] also use @litchar["{"] and @litchar["}"]. In
@racket[print] mode with @racket[print-as-expression] as @racket[#t]
and a @tech{quoting depth} of @racket[0], a mutable pair prints as
@litchar{(mcons }, the @racket[mcar] and @racket[mcdr] printed at
@tech{quoting depth} @racket[0] and separated by a space, and a
closing @litchar{)}.
If the @racket[print-pair-curly-braces] parameter is set to
@racket[#t], then pairs print using @litchar["{"] and @litchar["}"]
when not using @racket[print] mode with @racket[print-as-expression] as
@racket[#t] and a @tech{quoting depth} of @racket[0]. If the
@racket[print-mpair-curly-braces] parameter is set to @racket[#f],
then mutable pairs print using @litchar{(} and @litchar{)} in that
mode.
For the purposes of printing enclosing datatypes, an empty list is
always @tech{quotable}, a pair is @tech{quotable} when its
@racket[car] and @racket[cdr] are @tech{quotable}, and a mutable list
is never @tech{quotable}.
@history[#:changed "6.9.0.6" @elem{Added a space when printing @litchar{,}
or @litchar{#,} followed by a symbol
that prints with a leading @litchar["@"].}]
@section[#:tag "print-string"]{Printing Strings}
All @tech{strings} @racket[display] as their literal character sequences.
The @racket[write] or @racket[print] form of a string starts with @litchar{"} and ends
with another @litchar{"}. Between the @litchar{"}s, each character is
represented. Each graphic or blank character (according to @racket[char-graphic?] and
@racket[char-blank?]) is represented as itself,
with two exceptions: @litchar{"} is printed as @litchar{\"}, and
@litchar{\} is printed as @litchar{\\}. A non-graphic, non-blank character
that is part of a grapheme sequence that starts with a graphic character
is also represented as itself. Each other non-graphic, non-blank
character is printed using the escape sequences described
in @secref["parse-string"], using @litchar{\a}, @litchar{\b},
@litchar{\t}, @litchar{\n}, @litchar{\v}, @litchar{\f}, @litchar{\r},
or @litchar{\e} if possible, otherwise using @litchar{\u} with four
hexadecimal digits or @litchar{\U} with eight hexadecimal digits
(using the latter only if the character value does not fit into four
digits).
All byte strings @racket[display] as their literal byte sequence; this
byte sequence may not be a valid UTF-8 encoding, so it may not
correspond to a sequence of characters.
The @racket[write] or @racket[print] form of a byte string starts with @litchar{#"} and
ends with a @litchar{"}. Between the @litchar{"}s, each byte is
written using the corresponding ASCII decoding if the byte is between
0 and 127 and the character is graphic or blank (according to
@racket[char-graphic?] and @racket[char-blank?]). Otherwise, the byte
is written using @litchar{\a}, @litchar{\b}, @litchar{\t},
@litchar{\n}, @litchar{\v}, @litchar{\f}, @litchar{\r}, or
@litchar{\e} if possible, otherwise using @litchar{\} followed by one
to three octal digits (only as many as necessary).
For the purposes of printing enclosing datatypes, a string or a byte
string is @tech{quotable}.
@section[#:tag "print-vectors"]{Printing Vectors}
In @racket[display] mode, the printed form of a @tech{vector} is @litchar{#}
followed by the printed form of @racket[vector->list] applied to the
vector. In @racket[write] mode, the printed form is the same, except
that when the @racket[print-vector-length] parameter is @racket[#t], a
decimal integer is printed after the @litchar{#}, and a repeated last
element is printed only once.
Vectors @racket[print] the same as they @racket[write], unless
@racket[print-as-expression] is set to @racket[#t] and the current
@tech{quoting depth} is @racket[0]. In that case, if all of the
vector's elements are @tech{quotable}, then the vector's
@racket[print]ed form is prefixed with @litchar{'} and its elements
printed with @tech{quoting depth} @racket[1]. If its elements are not
all @tech{quotable}, then the vector @racket[print]s as
@litchar["(vector "], the elements at @tech{quoting depth} @racket[0],
and a closing @litchar{)}. A vector is @tech{quotable} when all of
its elements are @tech{quotable}.
In @racket[write] or @racket[display] mode, a @tech{flvector} prints
like a @tech{vector}, but with a @litchar{#fl} prefix instead of
@litchar{#}. A @tech{fxvector} similarly prints with a @litchar{#fx}
prefix instead of @litchar{#}. The @racket[print-vector-length]
parameter affects @tech{flvector} and @tech{fxvector} printing the
same as @tech{vector} printing. In @racket[print] mode,
@tech{flvectors} and @tech{fxvectors} are not @tech{quotable}, and
they print like a @tech{vector} at @tech{quoting depth} 0 using a
@litchar["(flvector "] or @litchar["(fxvector "] prefix, respectively.
@section[#:tag "print-structure"]{Printing Structures}
When the @racket[print-struct] parameter is set to @racket[#t], then
the way that @tech{structures} print depends on details of the structure type
for which the structure is an instance:
@itemize[
@item{If the structure type is a @tech{prefab} structure type,
then it prints in @racket[write] or @racket[display] mode using
@litchar{#s(} followed by the @tech{prefab} structure type key,
then the printed form of each field in the structure, and then
@litchar{)}.
In @racket[print] mode when @racket[print-as-expression] is set
to @racket[#t] and the current @tech{quoting depth} is
@racket[0], if the structure's content is all @tech{quotable},
then the structure's @racket[print]ed form is prefixed with
@litchar{'} and its content is printed with @tech{quoting
depth} @racket[1]. If any of its content is not quotable, then
the structure type prints the same as a non-@tech{prefab}
structure type.
An instance of a @tech{prefab} structure type is @tech{quotable}
when all of its content is @tech{quotable}.}
@item{If the structure has a @racket[prop:custom-write] property
value, then the associated procedure is used to print the
structure, unless the @racket[print-unreadable] parameter is
set to @racket[#f].
For @racket[print] mode, an instance of a structure type with a
@racket[prop:custom-write] property is treated as
@tech{quotable} if it has the
@racket[prop:custom-print-quotable] property with a value of
@racket['always]. If it has @racket['maybe] as the property
value, then the structure is treated as @tech{quotable} if its
content is @tech{quotable}, where the content is determined by
the values recursively printed by the structure's
@racket[prop:custom-write] procedure. Finally, if the structure
has @racket['self] as the property value, then it is treated as
@tech{quotable}.
In @racket[print] mode when @racket[print-as-expression] is
@racket[#t], the structure's @racket[prop:custom-write]
procedure is called with either @racket[0] or @racket[1] as the
@tech{quoting depth}, normally depending on the structure's
@racket[prop:custom-print-quotable] property value. If the
property value is @racket['always], the @tech{quoting depth} is
normally @racket[1]. If the property value is @racket['maybe],
then the @tech{quoting depth} is @racket[1] if the structure is
@tech{quotable}, or normally @racket[0] otherwise. If the
property value is @racket['self], then the quoting depth may be
@racket[0] or @racket[1]; it is normally @racket[0] if the
structure is not printed as a part of an enclosing
@tech{quotable} value, even though the structure is treated as
@tech{quotable}. Finally, if the property value is
@racket['never], then the @tech{quoting depth} is normally
@racket[0]. The @tech{quoting depth} can vary from its normal
value if the structure is printed with an explicit quoting
depth of @racket[1].}
@item{If the structure's type is transparent or if any ancestor is
transparent (i.e., @racket[struct?] on the instance produces
@racket[#t]), then the structure prints as the vector produced
by @racket[struct->vector] in @racket[display] mode, in
@racket[write] mode, or in @racket[print] mode when
@racket[print-as-expression] is set to @racket[#f] or when the
@tech{quoting depth} is @racket[0].
In @racket[print] mode with @racket[print-as-expression] as
@racket[#t] and a @tech{quoting depth} of @racket[0], the
structure content is printed with a @litchar{(} followed by
the structure's type name (as determined by
@racket[object-name]) in @racket[write] mode; the remaining
elements are @racket[print]ed at @tech{quoting depth}
@racket[0] and separated by a space, and finally a closing
@litchar{)}.
A transparent structure type that is not a @tech{prefab}
structure type is never @tech{quotable}.}
@item{For any other structure type, the structure prints as an
unreadable value; see @secref["print-unreadable"] for more
information.}
]
If the @racket[print-struct] parameter is set to @racket[#f], then all
structures without a @racket[prop:custom-write] property print as
unreadable values (see @secref["print-unreadable"]) and count as
@tech{quotable}.
@section[#:tag "print-hashtable"]{Printing Hash Tables}
When the @racket[print-hash-table] parameter is set to @racket[#t], in
@racket[write] and @racket[display] modes, a @tech{hash table} prints
starting with @litchar{#hash(}, @litchar{#hasheqv(}, or
@litchar{#hasheq(} for a table using @racket[equal?], @racket[eqv?],
or @racket[eq?] key comparisons, respectively, as long as the hash table
retains keys strongly. After the prefix, each
key--value mapping is shown as @litchar{(}, the printed form of a key,
a space, @litchar{.}, a space, the printed form the corresponding
value, and @litchar{)}, with an additional space if the key--value
pair is not the last to be printed. After all key--value pairs, the
printed form completes with @litchar{)}.
In @racket[print] mode when @racket[print-as-expression] is
@racket[#f] or the @tech{quoting depth} is @racket[1], the printed form
is the same as for @racket[write]. Otherwise, if the hash table's keys
and values are all @tech{quotable}, the table prints with a
@litchar{'} prefix, and the table's key and values are @racket[print]ed
at @tech{quoting depth} @racket[1]. If some key or value is not
@tech{quotable}, the hash table prints as @litchar["(hash "],
@litchar["(hasheqv "], or @litchar["(hasheq "] followed by alternating
keys and values @racket[print]ed at @tech{quoting depth} @racket[1] and
separated by spaces, and finally a closing @litchar{)}. A hash table
is @tech{quotable} when all of its keys and values are
@tech{quotable}.
When the @racket[print-hash-table] parameter is set to @racket[#f]
or when a hash table retains its keys weakly, a
hash table prints as @litchar{#<hash>} and counts as @tech{quotable}.
@section[#:tag "print-box"]{Printing Boxes}
When the @racket[print-box] parameter is set to @racket[#t], a @tech{box}
prints as @litchar{#&} followed by the printed form of its content in
@racket[write], @racket[display], or @racket[print] mode when
@racket[print-as-expression] is @racket[#f] or the @tech{quoting
depth} is @racket[1].
In @racket[print] mode when @racket[print-as-expression] is
@racket[#t] and the @tech{quoting depth} is @racket[0], a box prints
with a @litchar{'} prefix and its value is printed at @tech{quoting
depth} @racket[1] when its content is @tech{quotable}, otherwise the
box prints a @litchar["(box "] followed by the content at
@tech{quoting depth} @racket[0] and a closing @litchar{)}. A box is
@tech{quotable} when its content is @tech{quotable}.
When the @racket[print-box] parameter is set to @racket[#f], a box
prints as @litchar{#<box>} and counts as @tech{quotable}.
@section[#:tag "print-character"]{Printing Characters}
@tech{Characters} with the special names described in
@secref["parse-character"] @racket[write] and @racket[print] using the
same name. (Some characters have multiple names; the
@racket[#\newline] and @racket[#\nul] names are used instead of
@racketvalfont{#\linefeed} and @racketvalfont{#\null}.) Other graphic characters
(according to @racket[char-graphic?]) @racket[write] as @litchar{#\}
followed by the single character, and all others characters are
written in @racket[#\u] notation with four digits or @racket[#\U]
notation with eight digits (using the latter only if the character
value does not fit in four digits).
All characters @racket[display] directly as themselves (i.e., a single
character).
For the purposes of printing enclosing datatypes, a character is
@tech{quotable}.
@section[#:tag "print-keyword"]{Printing Keywords}
@tech{Keywords} @racket[write], @racket[print], and @racket[display] the same
as symbols (see @secref["print-symbol"]) except with a leading
@litchar{#:} (after any @litchar{'} prefix added in @racket[print]
mode), and without special handling for an initial @litchar{#} or when
the printed form would match a number or a delimited @litchar{.}
(since @litchar{#:} distinguishes the keyword).
For the purposes of printing enclosing datatypes, a keyword is
@tech{quotable}.
@section[#:tag "print-regexp"]{Printing Regular Expressions}
@tech{Regexp values} @racket[write], @racket[display], and @racket[print]
starting with @litchar{#px} (for @racket[pregexp]-based regexps) or
@litchar{#rx} (for @racket[regexp]-based regexps) followed by the
@racket[write] form of the regexp's source string or byte string.
For the purposes of printing enclosing datatypes, a regexp value is
@tech{quotable}.
@section[#:tag "print-path"]{Printing Paths}
@tech{Paths} @racket[write] and @racket[print] as @litchar{#<path:....>}. A
path @racket[display]s the same as the string produced by
@racket[path->string]. For the purposes of printing enclosing
datatypes, a path counts as @tech{quotable}.
Although a path can be converted to a string with
@racket[path->string] or to a byte string with @racket[path->bytes],
neither is clearly the right choice for printing a path and reading it
back. If the path value is meant to be moved among platforms, then a
string is probably the right choice, despite the potential for losing
information when converting a path to a string. For a path that is
intended to be re-read on the same platform, a byte string is probably
the right choice, since it preserves information in an unportable
way. Paths do not print in a readable way so that programmers are not
misled into thinking that either choice is always appropriate.
@section[#:tag "print-unreadable"]{Printing Unreadable Values}
For any value with no other printing specification, assuming that the
@racket[print-unreadable] parameter is set to @racket[#t], the output
form is @litchar{#<}@nonterm{something}@litchar{>}, where
@nonterm{something} is specific to the type of the value and sometimes
to the value itself. If @racket[print-unreadable] is set to
@racket[#f], then attempting to print an unreadable value raises
@racket[exn:fail].
For the purposes of printing enclosing datatypes, a value that prints
unreadably nevertheless counts as @tech{quotable}.
@section[#:tag "print-compiled"]{Printing Compiled Code}
Compiled code as produced by @racket[compile] prints using
@litchar{#~}. Compiled code printed with @litchar{#~} is essentially
assembly code for Racket, and reading such a form produces a compiled
form when the @racket[read-accept-compiled] parameter is set to
@racket[#t].
Compiled code parsed from @litchar{#~} is marked as non-runnable if
the current code inspector (see @racket[current-code-inspector]) is
not the original code inspector; on attempting to evaluate or reoptimize
non-runnable bytecode, @exnraise[exn:fail]. Otherwise, compiled
code parsed from @litchar{#~} may contain references to unexported or
protected bindings from a module. Conceptually, the references in
bytecode are associated with the current code inspector, where the
code will only execute if that inspector controls the relevant module
invocation (see @secref["modprotect"])---but the original code
inspector controls all other inspectors, anyway.
A compiled-form object may contain @tech{uninterned} symbols (see
@secref["symbols"]) that were created by @racket[gensym] or
@racket[string->uninterned-symbol]. When the compiled object is read
via @litchar{#~}, each uninterned symbol in the original form is
mapped to a new uninterned symbol, where multiple instances of a
single symbol are consistently mapped to the same new symbol. The
original and new symbols have the same printed
representation. @tech{Unreadable symbols}, which are typically
generated indirectly during expansion and compilation, are saved and
restored consistently through @litchar{#~}.
The dynamic nature of @tech{uninterned} symbols and their localization
within @litchar{#~} can cause problems when @racket[gensym] or
@racket[string->uninterned-symbol] is used to construct an identifier
for a top-level or module binding (depending on how the identifier and
its references are compiled). To avoid problems, generate distinct
identifiers either with @racket[generate-temporaries] or by applying
the result of @racket[make-syntax-introducer] to an existing
identifier; those functions lead to top-level and module variables
with @tech{unreadable symbol}ic names, and the names are deterministic
as long as expansion is otherwise deterministic.
When a compiled-form object has string and byte string literals, they
are @tech{interned} using @racket[datum-intern-literal] when the
compiled-object for is read back in. Numbers and other values that
@racket[read-syntax] would intern, however, are not interned when read
back as quoted literals in a compiled object.
A compiled form may contain path literals. Although paths are
not normally printed in a way that can be read back in, path literals
can be written and read as part of compiled code. The
@racket[current-write-relative-directory] parameter is used to convert
the path to a relative path as is it written, and then
@racket[current-load-relative-directory] parameter (falling back to
@racket[current-directory]) is used to convert
any relative path back as it is read.
For a path in a syntax object's source, if the
@racket[current-write-relative-directory] parameter is not set or the
path is not relative to the value of the
@racket[current-write-relative-directory] parameter, then the path is
coerced to a string that preserves only part of the path (an in effort
to make it less tied to the build-time filesystem, which can be
different than the run-time filesystem).
Finally, a compiled form may contain @racket[srcloc] structures if the
source field of the structure is a path for some system, a string, a
byte string, a symbol, or @racket[#f]. For a path value (matching the
current platform's convention), if the path cannot be recorded as a
relative path based on @racket[current-write-relative-directory], then
it is converted to a string with at most two path elements; if the
path contains more than two elements, then the string contains
@litchar{.../}, the next-to-last element, @litchar{/} and the last
element. The intent of the constraints on @racket[srcloc] values and
the conversion of the source field is to preserve some source
information but not expose or record a path that makes no sense on
a different filesystem or platform.
For internal testing purposes in the @tech{BC} implementation of Racket, when the
@as-index{@envvar{PLT_VALIDATE_LOAD}} environment variable is set, the
reader runs a validator on bytecode parsed from @litchar{#~}. The
validator may catch miscompilations or bytecode-file corruption. The
validator may run lazily, such as checking a procedure only when the
procedure is called.
@history[#:changed "6.90.0.21" @elem{Adjusted the effect of changing
the code inspector on parsed
bytecode, causing the reader to
mark the loaded code as generally
unrunnable instead of rejecting at
read time references to unsafe
operations.}
#:changed "7.0" @elem{Allowed some @racket[srcloc] values
embedded in compiled code.}]