diff --git a/quad/quads-typed.rkt b/quad/quads-typed.rkt index 20478005..be37654e 100644 --- a/quad/quads-typed.rkt +++ b/quad/quads-typed.rkt @@ -68,6 +68,11 @@ [else #f])] [else #f])) +(: quad-append (Quad QuadListItem . -> . Quad)) +(define (quad-append q new-item) + (quad (quad-name q) (quad-attrs q) (append (quad-list q) (list new-item)))) + + (provide gather-common-attrs) (: gather-common-attrs ((Listof Quad) . -> . (U False (Listof QuadAttrPair)))) diff --git a/quad/tests-typed.rkt b/quad/tests-typed.rkt index 3eedec1f..eebced5f 100644 --- a/quad/tests-typed.rkt +++ b/quad/tests-typed.rkt @@ -58,3 +58,15 @@ (check-true (quad-ends-with? (box #f (box #f "foo")) "o")) (check-true (quad-ends-with? (box #f (box #f (box #f (box #f (box #f "foo-"))))) "-")) +(check-equal? (quad-append (box #f "foo") "bar") (box #f "foo" "bar")) +(check-equal? (quad-append (box #f "foo") (box #f "bar")) (box #f "foo" (box #f "bar"))) + +(check-equal? (quad-last-char (box #f (box #f "foo") "food")) "d") +(check-equal? (quad-last-char (box #f (box #f "foo"))) "o") +(check-equal? (quad-last-char (box #f "foo")) "o") +(check-false (quad-last-char (box))) + +(check-equal? (quad-first-char (box #f (box #f "foo") "bar")) "f") +(check-equal? (quad-first-char (box #f (box #f "foo") "bar")) "f") +(check-equal? (quad-first-char (box #f "foo")) "f") +(check-false (quad-first-char (box))) diff --git a/quad/utils-typed.rkt b/quad/utils-typed.rkt index 8dbf271a..d56badb3 100644 --- a/quad/utils-typed.rkt +++ b/quad/utils-typed.rkt @@ -148,4 +148,29 @@ (: quad-attr-remove* (Quad QuadAttrKey * . -> . Quad)) (define (quad-attr-remove* q . ks) (for/fold ([current-q q])([k (in-list ks)]) - (quad-attr-remove current-q k))) \ No newline at end of file + (quad-attr-remove current-q k))) + + +;; the last char of a quad +(provide quad-last-char) +(: quad-last-char (Quad . -> . (Option String))) +(define (quad-last-char q) + (define split-qs (split-quad q)) ; split makes it simple, but is it too expensive? + (if (or (empty? split-qs) (empty? (quad-list (last split-qs)))) + #f + (let ([result((inst car QuadListItem QuadListItem) (quad-list (last split-qs)))]) + (if (quad? result) + (error 'quad-last-char "last element is not a string: ~v" result) + result)))) + +;; the first char of a quad +(provide quad-first-char) +(: quad-first-char (Quad . -> . (Option String))) +(define (quad-first-char q) + (define split-qs (split-quad q)) ; explosion makes it simple, but is it too expensive? + (if (or (empty? split-qs) (empty? (quad-list (first split-qs)))) + #f + (let ([result((inst car QuadListItem QuadListItem) (quad-list (first split-qs)))]) + (if (quad? result) + (error 'quad-first-char "first element is not a string: ~v" result) + result)))) \ No newline at end of file