convert racket value printer to constructor+quote style; update Guide and Quick

This commit is contained in:
Matthew Flatt 2010-05-06 14:57:15 -06:00
parent 43027a8d9b
commit 420ea6ee09
10 changed files with 488 additions and 286 deletions

View File

@ -124,7 +124,7 @@
(list
(hspace 2)
(elem #:style result-color
(to-element/no-color v #:qq? (print-as-expression)))))))))
(to-element/no-color v #:expr? (print-as-expression)))))))))
val-list))))
(loop (cdr expr-paras)
(cdr val-list+outputs)
@ -320,7 +320,7 @@
(define (show-val v)
(elem #:style result-color
(to-element/no-color v #:qq? (print-as-expression))))
(to-element/no-color v #:expr? (print-as-expression))))
(define (do-interaction-eval-show ev e)
(parameterize ([current-command-line-arguments #()])

View File

@ -162,23 +162,25 @@
e))))
(make-element style content)))
(define (to-quoted qs qq? quote-depth out color? inc!)
(if (and qq? (zero? quote-depth))
(define (to-quoted obj expr? quote-depth out color? inc!)
(if (and expr?
(zero? quote-depth)
(quotable? obj))
(begin
(out qs (and color? value-color))
(out "'" (and color? value-color))
(inc!)
(add1 quote-depth))
quote-depth))
(define (to-unquoted qq? quote-depth out color? inc!)
(if (or (not qq?) (zero? quote-depth))
(define (to-unquoted expr? quote-depth out color? inc!)
(if (or (not expr?) (zero? quote-depth))
quote-depth
(begin
(out "," (and color? meta-color))
(inc!)
(to-unquoted qq? (sub1 quote-depth) out color? inc!))))
(to-unquoted expr? (sub1 quote-depth) out color? inc!))))
(define (typeset-atom c out color? quote-depth qq?)
(define (typeset-atom c out color? quote-depth expr?)
(if (and (var-id? (syntax-e c))
(zero? quote-depth))
(out (format "~s" (let ([v (var-id-sym (syntax-e c))])
@ -203,13 +205,13 @@
is-var?)))
(values (substring s 1) #t #f)
(values s #f #f))))])
(let ([quote-depth (if (and qq? (identifier? c) (not (eq? qq-ellipses (syntax-e c))))
(let ([quote-depth (if (and expr? (identifier? c) (not (eq? qq-ellipses (syntax-e c))))
(let ([quote-depth
(if (and (quote-depth . < . 2)
(memq (syntax-e c) '(unquote unquote-splicing)))
(to-unquoted qq? quote-depth out color? void)
(to-unquoted expr? quote-depth out color? void)
quote-depth)])
(to-quoted "'" qq? quote-depth out color? void))
(to-quoted c expr? quote-depth out color? void))
quote-depth)])
(if (or (element? (syntax-e c))
(delayed-element? (syntax-e c))
@ -251,8 +253,8 @@
(define omitable (make-style #f '(omitable)))
(define (gen-typeset c multi-line? prefix1 prefix suffix color? qq?)
(let* ([c (syntax-ize c 0 #:qq? qq?)]
(define (gen-typeset c multi-line? prefix1 prefix suffix color? expr?)
(let* ([c (syntax-ize c 0 #:expr? expr?)]
[content null]
[docs null]
[first (syntax-case c (code:line)
@ -341,7 +343,7 @@
(set! src-col c)
(hash-set! next-col-map src-col dest-col)))]
[(c init-line!) (advance c init-line! 0)]))
(define (convert-infix c quote-depth qq?)
(define (convert-infix c quote-depth expr?)
(let ([l (syntax->list c)])
(and l
((length l) . >= . 3)
@ -367,7 +369,7 @@
(if val? value-color #f)
(list
(make-element/cache (if val? value-color paren-color) '". ")
(typeset a #f "" "" "" (not val?) qq?)
(typeset a #f "" "" "" (not val?) expr?)
(make-element/cache (if val? value-color paren-color) '" ."))
(+ (syntax-span a) 4)))
(list (syntax-source a)
@ -385,7 +387,7 @@
(cond
[(eq? s 'rsquo) "'"]
[else s]))
(define (loop init-line! quote-depth qq?)
(define (loop init-line! quote-depth expr? no-cons?)
(lambda (c)
(cond
[(eq? 'code:blank (syntax-e c))
@ -422,12 +424,13 @@
(set! dest-col 0)
(out "; " comment-color))
0
qq?)
expr?
#f)
l))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:line))
(let ([l (cdr (syntax->list c))])
(for-each (loop init-line! quote-depth qq?)
(for-each (loop init-line! quote-depth expr? #f)
l))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:hilite))
@ -439,19 +442,19 @@
(set! src-col (syntax-column (cadr l)))
(hash-set! next-col-map src-col dest-col)
(set! highlight? #t)
((loop init-line! quote-depth qq?) (cadr l))
((loop init-line! quote-depth expr?) (cadr l) #f)
(set! highlight? h?)
(set! src-col (add1 src-col)))]
[(and (pair? (syntax-e c))
(eq? (syntax-e (car (syntax-e c))) 'code:quote))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(let ([quote-depth (to-quoted c expr? quote-depth out color? inc-src-col)])
(out "(" (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 1))
(hash-set! next-col-map src-col dest-col)
((loop init-line! quote-depth qq?)
((loop init-line! quote-depth expr? #f)
(datum->syntax #'here 'quote (car (syntax-e c))))
(for-each (loop init-line! (add1 quote-depth) qq?)
(for-each (loop init-line! (add1 quote-depth) expr? #f)
(cdr (syntax->list c)))
(out ")" (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 1))
@ -463,12 +466,11 @@
quasisyntax syntax unsyntax unsyntax-splicing))
(let ([v (syntax->list c)])
(and v (= 2 (length v))))
(or (not qq?)
(quote-depth . > . 1)
(not (memq (syntax-e (car (syntax-e c)))
'(unquote unquote-splicing)))))
(or (not expr?)
(positive? quote-depth)
(quotable? c)))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(let ([quote-depth (to-quoted c expr? quote-depth out color? inc-src-col)])
(let-values ([(str quote-delta)
(case (syntax-e (car (syntax-e c)))
[(quote) (values "'" +inf.0)]
@ -485,12 +487,16 @@
(let ([i (cadr (syntax->list c))])
(set! src-col (or (syntax-column i) src-col))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (+ quote-depth quote-delta) qq?) i))))]
((loop init-line! (+ quote-depth quote-delta) expr? #f) i))))]
[(and (pair? (syntax-e c))
(convert-infix c quote-depth qq?))
(or (not expr?)
(positive? quote-depth)
(quotable? c))
(convert-infix c quote-depth expr?))
=> (lambda (converted)
((loop init-line! quote-depth qq?) converted))]
((loop init-line! quote-depth expr? #f) converted))]
[(or (pair? (syntax-e c))
(mpair? (syntax-e c))
(forced-pair? (syntax-e c))
(null? (syntax-e c))
(vector? (syntax-e c))
@ -498,12 +504,15 @@
(prefab-struct-key (syntax-e c)))
(struct-proxy? (syntax-e c)))
(let* ([sh (or (syntax-property c 'paren-shape)
#\()]
[quote-depth (if (and (not qq?)
(if (and (mpair? (syntax-e c))
(not (and expr? (zero? quote-depth))))
#\{
#\())]
[quote-depth (if (and (not expr?)
(zero? quote-depth)
(or (vector? (syntax-e c))
(struct? (syntax-e c))))
+inf.0
1
quote-depth)]
[p-color (if (positive? quote-depth)
value-color
@ -512,24 +521,50 @@
paren-color))])
(advance c init-line!)
(let ([quote-depth (if (struct-proxy? (syntax-e c))
(to-unquoted qq? quote-depth out color? inc-src-col)
(to-quoted "`" qq? quote-depth out color? inc-src-col))])
quote-depth
(to-quoted c expr? quote-depth out color? inc-src-col))])
(when (and expr? (zero? quote-depth))
(out "(" p-color)
(unless no-cons?
(out (let ([s (cond
[(pair? (syntax-e c))
(if (syntax->list c)
"list"
(if (let ([d (cdr (syntax-e c))])
(or (pair? d)
(and (syntax? d)
(pair? (syntax-e d)))))
"list*"
"cons"))]
[(vector? (syntax-e c)) "vector"]
[(mpair? (syntax-e c)) "mcons"]
[else (format "~a"
(if (struct-proxy? (syntax-e c))
(syntax-e (struct-proxy-name (syntax-e c)))
(object-name (syntax-e c))))])])
(set! src-col (+ src-col (string-length s)))
s)
symbol-color)
(out " " no-color)))
(when (vector? (syntax-e c))
(let ([vec (syntax-e c)])
(out "#" #; (format "#~a" (vector-length vec)) p-color)
(if (zero? (vector-length vec))
(set! src-col (+ src-col (- (syntax-span c) 2)))
(set! src-col (+ src-col (- (syntax-column (vector-ref vec 0))
(syntax-column c)
1))))))
(unless (and expr? (zero? quote-depth))
(let ([vec (syntax-e c)])
(out "#" p-color)
(if (zero? (vector-length vec))
(set! src-col (+ src-col (- (syntax-span c) 2)))
(set! src-col (+ src-col (- (syntax-column (vector-ref vec 0))
(syntax-column c)
1)))))))
(when (struct? (syntax-e c))
(out "#s" p-color)
(set! src-col (+ src-col 2)))
(out (case sh
[(#\[ #\?) "["]
[(#\{) "{"]
[else "("])
p-color)
(unless (and expr? (zero? quote-depth))
(out "#s" p-color)
(set! src-col (+ src-col 2))))
(unless (and expr? (zero? quote-depth))
(out (case sh
[(#\[ #\?) "["]
[(#\{) "{"]
[else "("])
p-color))
(set! src-col (+ src-col 1))
(hash-set! next-col-map src-col dest-col)
(let lloop ([l (cond
@ -539,31 +574,33 @@
(let ([l (vector->list (struct->vector (syntax-e c)))])
;; Need to build key datum, syntax-ize it internally, and
;; set the overall width to fit right:
(cons (let ([key (syntax-ize (prefab-struct-key (syntax-e c))
(+ 3 (or (syntax-column c) 0))
(or (syntax-line c) 1))]
[end (if (pair? (cdr l))
(and (equal? (syntax-line c) (syntax-line (cadr l)))
(syntax-column (cadr l)))
(and (syntax-column c)
(+ (syntax-column c) (syntax-span c))))])
(if end
(datum->syntax #f
(syntax-e key)
(vector #f (syntax-line key)
(syntax-column key)
(syntax-position key)
(- end 1 (syntax-column key))))
end))
(cdr l)))]
(if (and expr? (zero? quote-depth))
(cdr l)
(cons (let ([key (syntax-ize (prefab-struct-key (syntax-e c))
(+ 3 (or (syntax-column c) 0))
(or (syntax-line c) 1))]
[end (if (pair? (cdr l))
(and (equal? (syntax-line c) (syntax-line (cadr l)))
(syntax-column (cadr l)))
(and (syntax-column c)
(+ (syntax-column c) (syntax-span c))))])
(if end
(datum->syntax #f
(syntax-e key)
(vector #f (syntax-line key)
(syntax-column key)
(syntax-position key)
(max 1 (- end 1 (syntax-column key)))))
end))
(cdr l))))]
[(struct-proxy? (syntax-e c))
(cons
(struct-proxy-name (syntax-e c))
(struct-proxy-content (syntax-e c)))]
(struct-proxy-content (syntax-e c))]
[(forced-pair? (syntax-e c))
(syntax-e c)]
[(mpair? (syntax-e c))
(syntax-e c)]
[else c])]
[first-qq? (and qq? (not (struct-proxy? (syntax-e c))))]
[first-expr? (and expr? (not (struct-proxy? (syntax-e c))) (not no-cons?))]
[dotted? #f])
(cond
[(and (syntax? l)
@ -573,76 +610,94 @@
'(quote unquote syntax unsyntax quasiquote quasiunsyntax))
(let ([v (syntax->list l)])
(and v (= 2 (length v))))
(or (not qq?)
(or (not expr?)
(quote-depth . > . 1)
(not (memq (syntax-e (car (syntax-e l)))
'(unquote unquote-splicing)))))))
(lloop (syntax-e l) first-qq? #f)]
[(or (null? l)
(and (syntax? l)
(null? (syntax-e l))))
(lloop (syntax-e l) first-expr? #f)]
[(and (or (null? l)
(and (syntax? l)
(null? (syntax-e l)))))
(void)]
[(and (pair? l) (not dotted?))
((loop init-line! quote-depth first-qq?) (car l))
(lloop (cdr l) qq? #f)]
((loop init-line! quote-depth first-expr? #f) (car l))
(lloop (cdr l) expr? #f)]
[(forced-pair? l)
((loop init-line! quote-depth first-qq?) (forced-pair-car l))
(lloop (forced-pair-cdr l) qq? #t)]
((loop init-line! quote-depth first-expr? #f) (forced-pair-car l))
(lloop (forced-pair-cdr l) expr? #t)]
[(mpair? l)
((loop init-line! quote-depth first-expr? #f) (mcar l))
(lloop (mcdr l) expr? #t)]
[else
(advance l init-line! -2)
(out ". " (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 3))
(unless (and expr? (zero? quote-depth))
(advance l init-line! -2)
(out ". " (if (positive? quote-depth) value-color paren-color))
(set! src-col (+ src-col 3)))
(hash-set! next-col-map src-col dest-col)
((loop init-line! quote-depth first-qq?) l)]))
((loop init-line! quote-depth first-expr? #f) l)]))
(out (case sh
[(#\[ #\?) "]"]
[(#\{) "}"]
[else ")"])
p-color)
(set! src-col (+ src-col 1))
#;
(hash-set! next-col-map src-col dest-col)))]
(set! src-col (+ src-col 1))))]
[(box? (syntax-e c))
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out "#&" value-color)
(set! src-col (+ src-col 2))
(let ([quote-depth (to-quoted c expr? quote-depth out color? inc-src-col)])
(if (and expr? (zero? quote-depth))
(begin
(out "(" paren-color)
(out "box" symbol-color)
(out " " no-color)
(set! src-col (+ src-col 5)))
(begin
(out "#&" value-color)
(set! src-col (+ src-col 2))))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (if qq? quote-depth +inf.0) qq?) (unbox (syntax-e c))))]
((loop init-line! (if expr? quote-depth +inf.0) expr? #f) (unbox (syntax-e c)))
(when (and expr? (zero? quote-depth))
(out ")" paren-color)))]
[(hash? (syntax-e c))
(advance c init-line!)
(let ([equal-table? (hash-equal? (syntax-e c))]
[eqv-table? (hash-eq? (syntax-e c))]
[quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out (if equal-table?
"#hash"
(if eqv-table?
"#hasheqv"
"#hasheq"))
value-color)
(let ([delta (+ 5 (if equal-table? 0 (if eqv-table? 3 2)))]
[quote-depth (to-quoted c expr? quote-depth out color? inc-src-col)])
(unless (and expr? (zero? quote-depth))
(out (if equal-table?
"#hash"
(if eqv-table?
"#hasheqv"
"#hasheq"))
value-color))
(let ([delta (+ 5 (if equal-table? 0 (if eqv-table? 3 2))
(if (and expr? (zero? quote-depth)) 1 0))]
[orig-col src-col])
(set! src-col (+ src-col delta))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (if qq? quote-depth +inf.0) qq?)
((loop init-line! (if expr? quote-depth +inf.0) expr? (and expr? (zero? quote-depth)))
(let*-values ([(l) (sort (hash-map (syntax-e c) cons)
(lambda (a b)
(< (or (syntax-position (cdr a)) -inf.0)
(or (syntax-position (cdr b)) -inf.0))))]
[(col0) (+ (syntax-column c) delta 2)]
[(sep cap) (if (and expr? (zero? quote-depth))
(values 1 0)
(values 3 1))]
[(col0) (+ (syntax-column c) delta cap 1)]
[(l2 pos line) (for/fold ([l2 null][col col0][line (syntax-line c)])
([p (in-list l)])
(let* ([tentative (syntax-ize (car p) 0)]
(let* ([tentative (syntax-ize (car p) 0
#:expr? (and expr? (zero? quote-depth)))]
[width (syntax-span tentative)]
[col (if (= line (syntax-line (cdr p)))
col
col0)])
(let ([key
(let ([e (syntax-ize (car p)
(max 0 (- (syntax-column (cdr p))
width
3))
(syntax-line (cdr p)))])
(max 0 (- (syntax-column (cdr p))
width
sep))
(syntax-line (cdr p))
#:expr? (and expr? (zero? quote-depth)))])
(if ((syntax-column e) . <= . col)
e
(datum->syntax #f
@ -658,17 +713,42 @@
(make-forced-pair key (cdr p))
(vector 'here
(syntax-line (cdr p))
(max 0 (- (syntax-column key) 1))
(max 1 (- (syntax-position key) 1))
(+ (syntax-span (cdr p)) (syntax-span key) 5)))])
(max 0 (- (syntax-column key) cap))
(max 1 (- (syntax-position key) cap))
(+ (syntax-span (cdr p)) (syntax-span key) sep cap cap)))])
(values (cons elem l2)
(+ (syntax-column elem) (syntax-span elem) 2)
(syntax-line elem))))))])
(datum->syntax #f (reverse l2) (vector (syntax-source c)
(syntax-line c)
(+ (syntax-column c) delta)
(+ (syntax-position c) delta)
(max 1 (- (syntax-span c) delta))))))
(if (and expr? (zero? quote-depth))
;; constructed:
(let ([l (apply append
(map (lambda (p)
(let ([p (syntax-e p)])
(list (forced-pair-car p)
(forced-pair-cdr p))))
(reverse l2)))])
(datum->syntax
#f
(cons (let ([s (if equal-table?
'hash
(if eqv-table?
'hasheqv
'hasheq))])
(datum->syntax #f
s
(vector (syntax-source c)
(syntax-line c)
(+ (syntax-column c) 1)
(+ (syntax-position c) 1)
(string-length (symbol->string s)))))
l)
c))
;; quoted:
(datum->syntax #f (reverse l2) (vector (syntax-source c)
(syntax-line c)
(+ (syntax-column c) delta)
(+ (syntax-position c) delta)
(max 1 (- (syntax-span c) delta)))))))
(set! src-col (+ orig-col (syntax-span c)))))]
[(graph-reference? (syntax-e c))
(advance c init-line!)
@ -685,22 +765,22 @@
value-color
paren-color))
(set! src-col (+ src-col 3))
((loop init-line! quote-depth qq?) (graph-defn-r (syntax-e c))))]
[(and (keyword? (syntax-e c)) qq?)
((loop init-line! quote-depth expr? #f) (graph-defn-r (syntax-e c))))]
[(and (keyword? (syntax-e c)) expr?)
(advance c init-line!)
(let ([quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(typeset-atom c out color? quote-depth qq?)
(let ([quote-depth (to-quoted c expr? quote-depth out color? inc-src-col)])
(typeset-atom c out color? quote-depth expr?)
(set! src-col (+ src-col (or (syntax-span c) 1))))]
[else
(advance c init-line!)
(typeset-atom c out color? quote-depth qq?)
(typeset-atom c out color? quote-depth expr?)
(set! src-col (+ src-col (or (syntax-span c) 1)))
#;
(hash-set! next-col-map src-col dest-col)])))
(out prefix1 #f)
(set! dest-col 0)
(hash-set! next-col-map init-col dest-col)
((loop (lambda () (set! src-col init-col) (set! dest-col 0)) 0 qq?) c)
((loop (lambda () (set! src-col init-col) (set! dest-col 0)) 0 expr? #f) c)
(if (list? suffix)
(map (lambda (sfx)
(finish-line!)
@ -715,12 +795,13 @@
(make-table block-color (map list (reverse docs))))
(make-sized-element #f (reverse content) dest-col))))
(define (typeset c multi-line? prefix1 prefix suffix color? qq?)
(let* ([c (syntax-ize c 0 #:qq? qq?)]
(define (typeset c multi-line? prefix1 prefix suffix color? expr?)
(let* ([c (syntax-ize c 0 #:expr? expr?)]
[s (syntax-e c)])
(if (or multi-line?
(eq? 'code:blank s)
(pair? s)
(mpair? s)
(vector? s)
(struct? s)
(box? s)
@ -729,9 +810,9 @@
(graph-defn? s)
(graph-reference? s)
(struct-proxy? s)
(and qq? (or (identifier? c)
(and expr? (or (identifier? c)
(keyword? (syntax-e c)))))
(gen-typeset c multi-line? prefix1 prefix suffix color? qq?)
(gen-typeset c multi-line? prefix1 prefix suffix color? expr?)
(typeset-atom c
(letrec ([mk
(case-lambda
@ -743,19 +824,19 @@
(make-element/cache (and color? color) elem)
(make-sized-element (and color? color) elem len))])])
mk)
color? 0 qq?))))
color? 0 expr?))))
(define (to-element c #:qq? [qq? #f])
(typeset c #f "" "" "" #t qq?))
(define (to-element c #:expr? [expr? #f])
(typeset c #f "" "" "" #t expr?))
(define (to-element/no-color c #:qq? [qq? #f])
(typeset c #f "" "" "" #f qq?))
(define (to-element/no-color c #:expr? [expr? #f])
(typeset c #f "" "" "" #f expr?))
(define (to-paragraph c #:qq? [qq? #f])
(typeset c #t "" "" "" #t qq?))
(define (to-paragraph c #:expr? [expr? #f])
(typeset c #t "" "" "" #t expr?))
(define ((to-paragraph/prefix pfx1 pfx sfx) c #:qq? [qq? #f])
(typeset c #t pfx1 pfx sfx #t qq?))
(define ((to-paragraph/prefix pfx1 pfx sfx) c #:expr? [expr? #f])
(typeset c #t pfx1 pfx sfx #t expr?))
(begin-for-syntax
(define-struct variable-id (sym)
@ -886,8 +967,8 @@
(define-struct graph-reference (bx))
(define-struct graph-defn (r bx))
(define (syntax-ize v col [line 1] #:qq? [qq? #f])
(do-syntax-ize v col line (box #hasheq()) #f (and qq? 0)))
(define (syntax-ize v col [line 1] #:expr? [expr? #f])
(do-syntax-ize v col line (box #hasheq()) #f (and expr? 0) #f))
(define (graph-count ht graph?)
(and graph?
@ -897,23 +978,46 @@
(define-struct forced-pair (car cdr))
(define (do-syntax-ize v col line ht graph? qq)
(define (quotable? v)
(cond
[(syntax? v) (quotable? (syntax-e v))]
[(pair? v) (and (quotable? (car v))
(quotable? (cdr v)))]
[(vector? v) (andmap quotable? (vector->list v))]
[(hash? v) (for/and ([(k v) (in-hash v)])
(and (quotable? k)
(quotable? v)))]
[(box? v) (quotable? (unbox v))]
[(and (struct? v)
(prefab-struct-key v))
(andmap quotable? (vector->list (struct->vector v)))]
[(struct? v) (if (custom-write? v)
(if (and (custom-print-as-constructor? v)
(custom-print-as-constructor-accessor v))
#f
#t)
#f)]
[(struct-proxy? v) #f]
[(mpair? v) #f]
[else #t]))
(define (do-syntax-ize v col line ht graph? qq no-cons?)
(cond
[((syntax-ize-hook) v col)
=> (lambda (r) r)]
[(shaped-parens? v)
(syntax-property (do-syntax-ize (shaped-parens-val v) col line ht #f qq)
(syntax-property (do-syntax-ize (shaped-parens-val v) col line ht #f qq #f)
'paren-shape
(shaped-parens-shape v))]
[(just-context? v)
(let ([s (do-syntax-ize (just-context-val v) col line ht #f qq)])
(let ([s (do-syntax-ize (just-context-val v) col line ht #f qq #f)])
(datum->syntax (just-context-ctx v)
(syntax-e s)
s
s
(just-context-ctx v)))]
[(alternate-display? v)
(let ([s (do-syntax-ize (alternate-display-id v) col line ht #f qq)])
(let ([s (do-syntax-ize (alternate-display-id v) col line ht #f qq #f)])
(syntax-property s
'display-string
(alternate-display-string v)))]
@ -924,30 +1028,49 @@
(datum->syntax #f
(make-graph-reference m)
(vector #f line col (+ 1 col) 1)))]
[(and qq
(zero? qq)
(or (pair? v)
(forced-pair? v)
(vector? v)
(hash? v)
(box? v)
(and (struct? v)
(prefab-struct-key v)))
(quotable? v)
(not no-cons?))
;; Add a quote:
(let ([l (do-syntax-ize v (add1 col) line ht #f 1 #f)])
(datum->syntax #f
(syntax-e l)
(vector (syntax-source l)
(syntax-line l)
(sub1 (syntax-column l))
(max 0 (sub1 (syntax-position l)))
(add1 (syntax-span l)))))]
[(and (list? v)
(pair? v)
(or (not qq)
(positive? qq)
(quotable? v))
(let ([s (let ([s (car v)])
(if (just-context? s)
(just-context-val s)
s))])
(and
(or (memq s '(quaisquote quote))
(and (memq s '(unquote unquote-splicing))
(or (not qq)
(qq . > . 2))))
s)))
(memq s '(quote unquote unquote-splicing)))
(not no-cons?))
=> (lambda (s)
(let ([c (do-syntax-ize (cadr v) (+ col 1) line ht #f qq)])
(let* ([delta (if (and qq (zero? qq))
1
0)]
[c (do-syntax-ize (cadr v) (+ col delta) line ht #f qq #f)])
(datum->syntax #f
(list (do-syntax-ize (car v) col line ht #f
(and qq
(case s
[(quaisquote) (add1 qq)]
[(unquote unquote-splicing) (sub1 qq)]
[else qq])))
(list (do-syntax-ize (car v) col line ht #f qq #f)
c)
(vector #f line col (+ 1 col)
(+ 1 (syntax-span c))))))]
(+ 1
(if (and qq (zero? qq)) 1 0)
(syntax-span c))))))]
[(or (list? v)
(vector? v)
(and (struct? v)
@ -956,21 +1079,28 @@
(not (element? v)))
(prefab-struct-key v))))
(let ([orig-ht (unbox ht)]
[graph-box (box (graph-count ht graph?))]
[qq (and qq (max 1 qq))])
[graph-box (box (graph-count ht graph?))])
(set-box! ht (hash-set (unbox ht) v graph-box))
(let* ([graph-sz (if graph?
(+ 2 (string-length (format "~a" (unbox graph-box))))
0)]
[vec-sz (cond
[(vector? v)
(+ 1 #;(string-length (format "~a" (vector-length v))))]
(if (and qq (zero? qq)) 0 1)]
[(struct? v)
(if (prefab-struct-key v)
(if (and (prefab-struct-key v)
(or (not qq) (positive? qq)))
2
0)]
[else 0])]
[r (let ([l (let loop ([col (+ col 1 vec-sz graph-sz)]
[delta (if (and qq (zero? qq))
(cond
[(vector? v) 8]
[(struct? v) 1]
[no-cons? 1]
[else 5])
1)]
[r (let ([l (let loop ([col (+ col delta vec-sz graph-sz)]
[v (cond
[(vector? v)
(vector->short-list v values)]
@ -983,7 +1113,7 @@
[else v])])
(if (null? v)
null
(let ([i (do-syntax-ize (car v) col line ht #f qq)])
(let ([i (do-syntax-ize (car v) col line ht #f qq #f)])
(cons i
(loop (+ col 1 (syntax-span i)) (cdr v))))))])
(datum->syntax #f
@ -998,8 +1128,9 @@
(vector #f line
(+ graph-sz col)
(+ 1 graph-sz col)
(+ 2
(+ 1
vec-sz
delta
(if (zero? (length l))
0
(sub1 (length l)))
@ -1016,55 +1147,85 @@
[(unbox graph-box)
;; Go again, this time knowing that there will be a graph:
(set-box! ht orig-ht)
(do-syntax-ize v col line ht #t qq)]
(do-syntax-ize v col line ht #t qq #f)]
[else r])))]
[(or (pair? v)
(mpair? v)
(forced-pair? v))
(let ([carv (if (pair? v) (car v) (forced-pair-car v))]
[cdrv (if (pair? v) (cdr v) (forced-pair-cdr v))]
(let ([carv (if (pair? v) (car v) (if (mpair? v) (mcar v) (forced-pair-car v)))]
[cdrv (if (pair? v) (cdr v) (if (mpair? v) (mcdr v) (forced-pair-cdr v)))]
[orig-ht (unbox ht)]
[graph-box (box (graph-count ht graph?))]
[qq (and qq (max 1 qq))])
[graph-box (box (graph-count ht graph?))])
(set-box! ht (hash-set (unbox ht) v graph-box))
(let* ([inc (if graph?
(let* ([delta (if (and qq (zero? qq) (not no-cons?))
(if (mpair? v)
7 ; "(mcons "
(if (or (list? cdrv)
(not (pair? cdrv)))
6 ; "(cons "
7)) ; "(list* "
1)]
[inc (if graph?
(+ 2 (string-length (format "~a" (unbox graph-box))))
0)]
[a (do-syntax-ize carv (+ col 1 inc) line ht #f qq)]
[a (do-syntax-ize carv (+ col delta inc) line ht #f qq #f)]
[sep (if (and (pair? v)
(pair? cdrv)
;; FIXME: what if it turns out to be a graph reference?
(not (hash-ref (unbox ht) cdrv #f)))
0
3)]
[b (do-syntax-ize cdrv (+ col 1 inc (syntax-span a) sep) line ht #f qq)])
(if (and qq (zero? qq))
1
3))]
[b (do-syntax-ize cdrv (+ col delta inc (syntax-span a) sep) line ht #f qq #t)])
(let ([r (datum->syntax #f
(cons a b)
(vector #f line (+ col inc) (+ 1 col inc)
(+ 2 sep (syntax-span a) (syntax-span b))))])
(if (mpair? v)
(mcons a b)
(cons a b))
(vector #f line (+ col inc) (+ delta col inc)
(+ 1 delta
(if (and qq (zero? qq)) 1 0)
sep (syntax-span a) (syntax-span b))))])
(unless graph?
(set-box! ht (hash-set (unbox ht) v #f)))
(cond
[graph? (datum->syntax #f
(make-graph-defn r graph-box)
(vector #f line col (+ 1 col)
(vector #f line col (+ delta col)
(+ inc (syntax-span r))))]
[(unbox graph-box)
;; Go again...
(set-box! ht orig-ht)
(do-syntax-ize v col line ht #t qq)]
(do-syntax-ize v col line ht #t qq #f)]
[else r]))))]
[(box? v)
(let ([a (do-syntax-ize (unbox v) (+ col 2) line ht #f (and qq (max 1 qq)))])
(let* ([delta (if (and qq (zero? qq))
5 ; "(box "
2)] ; "#&"
[a (do-syntax-ize (unbox v) (+ col delta) line ht #f qq #f)])
(datum->syntax #f
(box a)
(vector #f line col (+ 1 col)
(+ 2 (syntax-span a)))))]
(+ delta (if (and qq (zero? qq)) 1 0) (syntax-span a)))))]
[(hash? v)
(let* ([delta (cond
[(hash-eq? v) 7]
[(hash-eqv? v) 8]
[else 6])]
[pairs (do-syntax-ize (hash-map v make-forced-pair) (+ col delta) line ht #f (and qq (max 1 qq)))])
[undelta (if (and qq (zero? qq))
(- delta 1)
0)]
[pairs (if (and qq (zero? qq))
(let ([ls (do-syntax-ize (apply append (hash-map v (lambda (k v) (list k v))))
(+ col delta -1) line ht #f qq #t)])
(datum->syntax
#f
(let loop ([l (syntax->list ls)])
(if (null? l)
null
(cons (cons (car l) (cadr l)) (loop (cddr l)))))
ls))
(do-syntax-ize (hash-map v make-forced-pair) (+ col delta) line ht #f qq #f))])
(datum->syntax #f
((cond
[(hash-eq? v) make-immutable-hasheq]
@ -1075,6 +1236,10 @@
(cons (syntax->datum (car p))
(cdr p))))
(syntax->list pairs)))
pairs))]
(vector (syntax-source pairs)
(syntax-line pairs)
(max 0 (- (syntax-column pairs) undelta))
(max 1 (- (syntax-position pairs) undelta))
(+ (syntax-span pairs) undelta))))]
[else
(datum->syntax #f v (vector #f line col (+ 1 col) 1))])))

View File

@ -5,9 +5,9 @@
@title[#:tag "boxes"]{Boxes}
A @deftech{box} is like a single-element vector. It prints as
@litchar{#&} followed by the printed form of the boxed value. A
@litchar{#&} form can also be used as an expression, but since the
A @deftech{box} is like a single-element vector. It can print as a
quoted @litchar{#&} followed by the printed form of the boxed value.
A @litchar{#&} form can also be used as an expression, but since the
resulting box is constant, it has practically no use.
@; So what are boxes good for, anyway?

View File

@ -8,9 +8,9 @@
A @deftech{hash table} implements a mapping from keys to values, where
both keys and values can be arbitrary Scheme values, and access and
update to the table are normally constant-time operations. Keys are
compared using @scheme[equal?] or @scheme[eq?], depending on whether
the hash table is created with @scheme[make-hash] or
@scheme[make-hasheq].
compared using @scheme[equal?], @scheme[eqv?], or @scheme[eq?], depending on whether
the hash table is created with @scheme[make-hash],
@scheme[make-hasheqv], or @scheme[make-hasheq].
@examples[
(define ht (make-hash))
@ -21,29 +21,50 @@ the hash table is created with @scheme[make-hash] or
(hash-ref ht "coconut" "not there")
]
A literal hash table can be written as an expression by using
The @racket[hash], @racket[hasheqv], and @racket[hasheq] functions
create immutable hash tables from an initial set of keys and values,
which each value is provided as an argument after its key. Immutable
hash tables can be extended with @scheme[hash-set], which produces a
new immutable hash table in constant time.
@examples[
(define ht (hash "apple" 'red "banana" 'yellow))
(hash-ref ht "apple")
(define ht2 (hash-set ht "coconut" 'brown))
(hash-ref ht "coconut")
(hash-ref ht2 "coconut")
]
A literal immutable hash table can be written as an expression by using
@litchar{#hash} (for an @scheme[equal?]-based table),
@litchar{#hasheq} (for an @scheme[eq?]-based table), or
@litchar{#hasheqv} (for an @scheme[eqv?]-based table). A parenthesized
@litchar{#hasheqv} (for an @scheme[eqv?]-based table), or
@litchar{#hasheq} (for an @scheme[eq?]-based table). A parenthesized
sequence must immediately follow @litchar{#hash}, @litchar{#hasheq},
or @litchar{#hasheqv}, where each element is a sequence is a dotted
key--value pair. Literal hash tables are immutable, but they can be
extended functionally (producing a new hash table without changing the
old one) using @scheme[hash-set].
key--value pair. The @litchar{#hash}, etc. forms implicitly
@scheme[quote] their key and value sub-forms.
@examples[
(define ht #hash(("apple" . red)
("banana" . yellow)))
(hash-ref ht "apple")
(define ht2 (hash-set ht "coconut" 'brown))
(hash-ref ht "coconut")
(hash-ref ht2 "coconut")
ht2
]
@refdetails/gory["parse-hashtable"]{the syntax of hash table literals}
A non-literal hash table can optionally retain its keys
Both mutable and immutable hash tables print like immutable hash
tables, using a quoted @litchar{#hash}, @litchar{#hasheqv}, or
@litchar{#hasheq} form if all keys and values can be expressed with
@scheme[quote] or using @racketresult[hash], @racketresult[hasheq], or
@racketresult[hasheqv] otherwise:
@examples[
#hash(("apple" . red)
("banana" . yellow))
(hash 1 (srcloc "file.rkt" 1 0 1 (+ 4 4)))
]
A mutable hash table can optionally retain its keys
@defterm{weakly}, so each mapping is retained only so long as the key
is retained elsewhere.

View File

@ -23,12 +23,16 @@ a list containing the values:
@interaction[(list "red" "green" "blue")
(list 1 2 3 4 5)]
As you can see, a list result prints in the @tech{REPL} as a backquote
@litchar{`} and then a pair of parentheses wrapped around the printed
@margin-note{A list usually prints with @litchar{'}, but the printed
form of a list depends on its content. See
@secref["pairs"] for more information.}
As you can see, a list result prints in the @tech{REPL} as a quote
@litchar{'} and then a pair of parentheses wrapped around the printed
form of the list elements. There's an opportunity for confusion here,
because parentheses are used for both expressions, such as
@racket[(list "red" "green" "blue")], and printed results, such as
@racketresult['("red" "green" "blue")]. In addition to the backquote,
@racketresult['("red" "green" "blue")]. In addition to the quote,
parentheses for results are printed in blue in the documentation and
in DrRacket, whereas parentheses for expressions are brown.

View File

@ -11,7 +11,7 @@ procedures extract the first and second elements of the pair,
respectively. The @scheme[pair?] predicate recognizes pairs.
Some pairs print by wrapping parentheses around the printed forms of
the two pair elements, putting a @litchar{`} at the beginning and a
the two pair elements, putting a @litchar{'} at the beginning and a
@litchar{.} between the elements.
@examples[
@ -28,7 +28,7 @@ or it is a pair whose first element is a list element and whose second
element is a list. The @scheme[list?] predicate recognizes lists. The
@scheme[null?] predicate recognizes the empty list.
A list prints as a @litchar{`} followed by a pair of parentheses
A list normally prints as a @litchar{'} followed by a pair of parentheses
wrapped around the list elements.
@examples[
@ -39,28 +39,37 @@ null
(list? (cons 1 2))
]
The @scheme[display] function prints a pair or list without a leading
@litchar{`}:
A list or pair prints using @schemeresult[list] or @schemeresult[cons]
when one of its elements cannot be written as a @scheme[quote]d
value. For example, a value constructed with @racket[srcloc] cannot be
written using @scheme[quote], and it prints using @racketresult[srcloc]:
@examples[
(display (cons 1 2))
(display null)
(display (list 1 2 3))
@interaction[
(srcloc "file.rkt" 1 0 1 (+ 4 4))
(list 'here (srcloc "file.rkt" 1 0 1 8) 'there)
(cons 1 (srcloc "file.rkt" 1 0 1 8))
(cons 1 (cons 2 (srcloc "file.rkt" 1 0 1 8)))
]
Pairs are immutable (contrary to Lisp tradition), and @scheme[pair?]
and @scheme[list?] recognize immutable pairs and lists, only. The
@scheme[mcons] procedure creates a mutable pair, which works with
@scheme[set-mcar!] and @scheme[set-mcdr!], as well as @scheme[mcar]
and @scheme[mcdr].
@margin-note{See also @racket[list*].}
As shown in the last example, @schemeresult[list*] is used to
abbreviate a series of @schemeresult[cons]es that cannot be
abbreviated using @racketresult[list].
The @scheme[write] and @scheme[display] functions print a pair or list
without a leading @litchar{'}, @schemeresult[cons],
@schemeresult[list], or @schemeresult[list*]. There is no difference
between @scheme[write] and @racket[display] for a pair or list, except
as they apply to elements of the list:
@examples[
(define p (mcons 1 2))
p
(pair? p)
(mpair? p)
(set-mcar! p 0)
p
(write (cons 1 2))
(display (cons 1 2))
(write null)
(display null)
(write (list 1 2 "3"))
(display (list 1 2 "3"))
]
Among the most important predefined procedures on lists are those that
@ -87,3 +96,23 @@ iterate through the list's elements:
]
@refdetails["pairs"]{pairs and lists}
Pairs are immutable (contrary to Lisp tradition), and @scheme[pair?]
and @scheme[list?] recognize immutable pairs and lists, only. The
@scheme[mcons] procedure creates a @deftech{mutable pair}, which works
with @scheme[set-mcar!] and @scheme[set-mcdr!], as well as
@scheme[mcar] and @scheme[mcdr]. A mutable pair prints using
@schemeresult[mcons], while @scheme[write] and @scheme[display] print
mutable pairs with @litchar["{"] and @litchar["}"]:
@examples[
(define p (mcons 1 2))
p
(pair? p)
(mpair? p)
(set-mcar! p 0)
p
(write p)
]
@refdetails["mpairs"]{mutable pairs}

View File

@ -61,11 +61,14 @@ special characters or that might otherwise look like numbers.
@refdetails/gory["parse-symbol"]{the syntax of symbols}
The @racket[display] form of a symbol is the same as the corresponding
string.
The @racket[write] function prints a symbol without a @litchar{'}
prefix. The @racket[display] form of a symbol is the same as the
corresponding string.
@examples[
(write 'Apple)
(display 'Apple)
(write '|6|)
(display '|6|)
]

View File

@ -69,27 +69,27 @@ a pair, but @italic{is not} a list:
In general, the rule for printing a pair is as follows: use the dot
notation always, but if the dot is immediately followed by an open
parenthesis, then remove the dot, the open parenthesis, and the
matching close parenthesis. Thus, @racketresultfont{`(0 . (1 . 2))}
becomes @racketresult[`(0 1 . 2)], and
@racketresultfont{`(1 . (2 . (3 . ())))} becomes @racketresult[`(1 2 3)].
matching close parenthesis. Thus, @racketresultfont{'(0 . (1 . 2))}
becomes @racketresult['(0 1 . 2)], and
@racketresultfont{'(1 . (2 . (3 . ())))} becomes @racketresult['(1 2 3)].
@;------------------------------------------------------------------------
@section[#:tag "quoting-lists"]{Quoting Pairs and Symbols with @racket[quote]}
After you see
A list prints with a quote mark before it, but if an element of a list
is itself a list, then no quote mark is printed for the inner list:
@interaction[
(list (list 1) (list 2) (list 3))
(list (list 1) (list 2 3) (list 4))
]
enough times, you'll wish (or you're already wishing) that there was a
way to write just @racket[((1) (2) (3))] and have it mean the list of
lists that prints as @racketresult[`((1) (2) (3))]. The @racket[quote]
form does exactly that:
For nested lists, especially, the @racket[quote] form lets you write a
list as an expression in essentially the same way that the list it
prints:
@interaction[
(eval:alts (@#,racket[quote] ((1) (2) (3))) '((1) (2) (3)))
(eval:alts (@#,racket[quote] ("red" "green" "blue")) '("red" "green" "blue"))
(eval:alts (@#,racket[quote] ((1) (2 3) (4))) '((1) (2 4) (4)))
(eval:alts (@#,racket[quote] ()) '())
]
@ -116,7 +116,7 @@ that looks like an identifier, but with a @litchar{'} prefix:
(eval:alts (@#,racket[quote] jane-doe) 'jane-doe)
]
A value that prints like an identifier is a @defterm{symbol}. In the
A value that prints like a quoted identifier is a @defterm{symbol}. In the
same way that parenthesized output should not be confused with
expressions, a printed symbol should not be confused with an
identifier. In particular, the symbol @racket[(@#,racket[quote]
@ -141,28 +141,38 @@ map
(eval:alts (symbol->string (@#,racket[quote] @#,racketidfont{map})) (symbol->string 'map))
]
When @racket[quote] is used on a parenthesized sequence of
identifiers, it creates a list of symbols:
In the same way that @racket[quote] for a list automatically applies
itself to nested lists, @racket[quote] on a parenthesized sequence of
identifiers automatically applies itself to the identifiers to create
a list of symbols:
@interaction[
(eval:alts (car (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map}))) (car '(road map)))
(eval:alts (symbol? (car (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map})))) (symbol? (car '(road map))))
]
When a symbol is inside a
list that is printed with @litchar{`}, the @litchar{'} on the symbol
is omitted, since @litchar{`} is doing the job already:
When a symbol is inside a list that is printed with
@litchar{'}, the @litchar{'} on the symbol is omitted, since
@litchar{'} is doing the job already:
@interaction[
(eval:alts (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map})) '(road map))
]
The @racket[quote] form has no effect on a literal expression such as
a number or string:
@interaction[
(eval:alts (@#,racket[quote] 42) 42)
(eval:alts (@#,racket[quote] "on the record") "on the record")
]
@;------------------------------------------------------------------------
@section{Abbreviating @racket[quote] with @racketvalfont{'}}
If @racket[(@#,racket[quote] (1 2 3))] still seems like too much
typing, you can abbreviate by just putting @litchar{'} in front of
@racket[(1 2 3)]:
As you may have guessed, you can abbreviate a use of
@racket[quote] by just putting @litchar{'} in front of a form to
quote:
@interaction[
'(1 2 3)
@ -183,58 +193,25 @@ way. You can see this if you put a @litchar{'} in front of a form that has a
@litchar{'}:
@interaction[
(eval:alts (car '(@#,racketvalfont{quote} @#,racketvalfont{road})) 'quote)
(car ''road)
(eval:alts (car '(@#,racketvalfont{quote} @#,racketvalfont{road})) 'quote)
]
Beware, however, that the @tech{REPL}'s printer recognizes the symbol
@racketidfont{quote} when printing output, and then it uses
@racketidfont{'} in the output:
The @litchar{'} abbreviation works in output as well as input. The
@tech{REPL}'s printer recognizes the symbol @racket['quote] as the
first element of a two-element list when printing output, in which
case it uses @racketidfont{'} to print the output:
@interaction[
(eval:alts (list (@#,racketvalfont{quote} (@#,racketvalfont{quote} @#,racketvalfont{road}))) '('road))
(list ''road)
(eval:alts (@#,racketvalfont{quote} (@#,racketvalfont{quote} @#,racketvalfont{road})) ''road)
(eval:alts '(@#,racketvalfont{quote} @#,racketvalfont{road}) ''road)
''road
]
@; FIXME:
@; warning about how "quote" creates constant data, which is subtly
@; different than what "list" creates
@;------------------------------------------------------------------------
@section{Quasiquoting with @racketvalfont{`}}
At this point, you may wonder why a symbol that is written with
@litchar{'} prints back with @litchar{'}, while a list that is written
with @litchar{'} prints back with @litchar{`}:
@interaction[
'road
'(left right)
]
The @litchar{`} character is a shorthand for @racket[quasiquote] in
the same way that @litchar{'} is short for @racket[quote]. The
@racket[quasiquote] form is like @scheme[quote], except that the
content of a @scheme[quasiquote]d form can escape back to a Racket
expression using @racket[unquote], which is abbreviated @litchar{,}:
@moreguide["qq"]{@racket[quasiquote]}
@interaction[
`(1 ,(+ 1 1) "buckle my shoe")
]
The value printer in Racket uses @litchar{`} for a lists in case it
must escape to print certain kinds of values that cannot be written
directly under @scheme[quote]. For example, a source-location record
is created with the @racket[srcloc] function, and it prints like an
equivalent call to @racket[srcloc]:
@interaction[
(srcloc "file.rkt" 1 0 1 (+ 4 4))
(list 'here (srcloc "file.rkt" 1 0 1 8) 'there)
]
@;------------------------------------------------------------------------
@section[#:tag "lists-and-syntax"]{Lists and Racket Syntax}

View File

@ -10,11 +10,14 @@ values. Unlike a list, a vector supports constant-time access and
update of its elements.
A vector prints similar to a list---as a parenthesized sequence of its
elements---but a vector is prefixed with @litchar{#}. For a vector as
an expression, an optional length can be supplied. Also, a vector as
an expression implicitly quotes the forms for its content, which means
that identifiers and parenthesized forms in a vector constant
represent symbols and lists.
elements---but a vector is prefixed with @litchar{#} after
@litchar{'}, or it uses @schemeresult[vector] of one of its elements
cannot be expressed with @racket[quote].
For a vector as an expression, an optional length can be
supplied. Also, a vector as an expression implicitly @racket[quote]s
the forms for its content, which means that identifiers and
parenthesized forms in a vector constant represent symbols and lists.
@refdetails/gory["parse-vector"]{the syntax of vectors}

View File

@ -318,11 +318,11 @@ a list containing the given values:
@mr-interaction[(list "red" "green" "blue")
(list (circle 10) (square 10))]
As you can see, a list prints as a backquoted pair of parentheses wrapped around
As you can see, a list prints as a single quote and then pair of parentheses wrapped around
the printed form of the list elements. There's room for confusion
here, because parentheses are used for both expressions, such as
@racket[(circle 10)], and printed results, such as
@racketresult[`("red" "green" "blue")]. The backquote is the key difference,
@racketresult['("red" "green" "blue")]. The quote is the key difference,
as @seclink[#:doc '(lib "scribblings/guide/guide.scrbl") "quoting-lists"]{discussed
elsewhere}. To help emphasize the difference, in the documentation and in DrRacket,
result parentheses are printed in blue, unlike expression parentheses.