allow duplicate attrs

main
Matthew Butterick 6 years ago
parent ca25159120
commit 2ff47497d7

@ -6,15 +6,15 @@
(define/contract (atomize qx)
;; normalize a qexpr by reducing it to one-character quads.
;; propagate attrs downward by appending to front of attrs list.
;; at then end, duplicates are removed, with frontmost attrs (= added later) given preference
;; ok to have duplicate attrs (leftmost attr takes precedence)
(qexpr? . -> . (listof qexpr?))
(let loop ([x qx][attrs null])
(match x
[(? string?) (for/list ([c (in-string x)]) ;; strings are exploded
(qexpr attrs (string c)))]
(qexpr attrs (string c)))]
[(list (? symbol?) (? txexpr-attrs? new-attrs) xs ...) ;; qexprs with attributes are recursed
(append* (for/list ([x (in-list xs)])
(loop x (append new-attrs attrs))))]
(loop x (append new-attrs attrs))))]
[(list (? symbol? tag) xs ...) (loop (list* tag null xs) attrs)] ;; qexprs without attributes get null attrs
[else (raise-argument-error 'atomize "valid item" x)])))
@ -34,9 +34,9 @@
(q ((k "v")) "o")
(q ((k "v")) "u")))
(check-equal? (atomize '(q ((k1 "v1")(k2 "42")) "Hi " (q ((k1 "v2")(k3 "foo")) "You")))
'((q ((k1 "v1")(k2 "42")) "H")
(q ((k1 "v1")(k2 "42")) "i")
(q ((k1 "v1")(k2 "42")) " ")
(q ((k1 "v2")(k3 "foo")(k2 "42")) "Y")
(q ((k1 "v2")(k3 "foo")(k2 "42")) "o")
(q ((k1 "v2")(k3 "foo")(k2 "42")) "u"))))
'((q ((k1 "v1") (k2 "42")) "H")
(q ((k1 "v1") (k2 "42")) "i")
(q ((k1 "v1") (k2 "42")) " ")
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "Y")
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "o")
(q ((k1 "v2") (k3 "foo") (k1 "v1") (k2 "42")) "u"))))

@ -26,14 +26,16 @@
(check-true (qexpr? '(quad "Hello world")))
(check-false (qexpr? 'q)))
(define/contract (qexpr attrs . elems)
((txexpr-attrs?) #:rest txexpr-elements? . ->* . qexpr?)
(txexpr 'q (remove-duplicates attrs #:key car) elems))
(define/contract (qexpr #:clean-attrs? [clean-attrs? #f]
attrs . elems)
((txexpr-attrs?) (#:clean-attrs? any/c) #:rest txexpr-elements? . ->* . qexpr?)
(txexpr 'q (if clean-attrs? (remove-duplicates attrs #:key car) attrs) elems))
(module+ test
(check-equal? (qexpr null "foo") '(q "foo"))
(check-equal? (qexpr '((k "v")) "foo") '(q ((k "v")) "foo"))
(check-equal? (qexpr '((k "v2")(k "v1")) "foo") '(q ((k "v2")) "foo")))
(check-equal? (qexpr '((k "v2")(k "v1")) "foo") '(q ((k "v2")(k "v1")) "foo"))
(check-equal? (qexpr #:clean-attrs? #t '((k "v2")(k "v1")) "foo") '(q ((k "v2")) "foo")))
(define/contract (qml->qexpr x)
(string? . -> . qexpr?)

Loading…
Cancel
Save