convert racket value printer to constructor+quote style; update Guide and Quick
This commit is contained in:
parent
43027a8d9b
commit
420ea6ee09
|
@ -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 #()])
|
||||
|
|
|
@ -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))])))
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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|)
|
||||
]
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue
Block a user