;; ;; Like normal lisp strings, dstrings are immutable, but unlike normal ;; lisp strings, appending to a dstring is efficient. The downside is ;; that dstrings are literally lists of characters, but the list holds ;; the characters in reverse order. Thus, the client must remember to ;; call (dstring-get-value) to convert back to a normal lisp string. ;; (defun make-dstring (s) "Convert the string S to a dstring. If S is already a dstring, it is returned without conversion. Calling (dstring-append) with just one argument has the same effect as calling this method." (ctypecase s (string (reverse (coerce s 'list))) (list s))) (defun dstring-append (&rest args) "Append all the dstrings or normal lisp strings in ARGS and return the result as a dstring. The client must call (dstring-get-value) to convert the returned dstring to a normal lisp string." ;; Iterate over each dstring or string in ARGS. (reduce (lambda (acc s) ;; Iterate over each character in the string appending it ;; to the accumulator. (reduce (lambda (c acc) (cons c acc)) (make-dstring s) :initial-value acc :from-end t)) args :initial-value (make-dstring ""))) (defun dstring-append-line (&rest args) "Append all the dstrings or normal lisp strings in ARGS and return the result as a dstring with a trailing #\\newline character appended. The client must call (dstring-get-value) to convert the returned dstring to a normal lisp string." (cons #\newline (apply #'dstring-append args))) (defun dstring-get-value (ds) "Return the dstring DS as normal lisp string. If DS is already a normal lisp string, it is returned without conversion." (ctypecase ds (string ds) (list (coerce (reverse ds) 'string))))