;; A Text is a (Listof Symbol) ;; The symbols represent individual characters, ;; including punctuation, spaces and newlines ;; A Lined-Text is a (Listof (Listof Symbol)) (define sample-text (list 'M 'a 'r 'y 'SP 'h 'a 'd 'SP 'a 'NL 'l 'i 't 't 'l 'e 'SP 'l 'a 'm 'b 'PE 'NL 'I 't 's 'SP 'f 'l 'e 'e 'c 'e 'SP 'w 'a 's 'NL 'w 'h 'i 't 'e 'SP 'a 's 'SP 's 'n 'o 'w 'PE)) ;;;;;;;;;;;; Structural version, with accumulator ;;;;;;;;;;;;;;; ;; break-lines : Text -> Lined-Text ;; turns each line of the original text into a separate sublist (define (break-lines text) (break-aux text empty)) ;; break-aux : Text Text -> Lined-Text ;; turns each line of text into a separate sublist ;; accum collects characters that will form the current line (define (break-aux text accum) (cond [(empty? text) (if (empty? accum) empty (list (reverse accum)))] [else (cond [(symbol=? (first text) 'NL) (cons (reverse accum) (break-aux (rest text) empty))] [else (break-aux (rest text) (cons (first text) accum))])])) (break-lines sample-text) ;;;;;;;;;;;;; Generative recursion version ;;;;;;;;;;;;;;;;;;;;;; ;; This is generative recursion and not structural recursion because ;; the recursive call is not made on the rest of the input. ;; break-lines2: Text -> Lined-Text ;; turns each line of the original text into a separate sublist (define (break-lines2 text) (cond [(empty? text) empty] [else (cons (first-line text) (break-lines (rest-lines text)))])) ;; first-line : Text -> Text ;; produce list of all characters up to the first 'NL (or until the list runs out) ;; uses structural recursion (define (first-line text) (cond [(empty? text) empty] [else (cond [(symbol=? (first text) 'NL) empty] [else (cons (first text) (first-line (rest text)))])])) ;; rest-lines : Text -> Text ;; remove all characters up to (and including) the first 'NL ;; uses structural recursion (define (rest-lines text) (cond [(empty? text) empty] [else (cond [(symbol=? (first text) 'NL) (rest text)] [else (rest-lines (rest text))])])) (break-lines2 sample-text)