;; A Visitor is a structure made up of two functions ;; One for the base case and ;; one for the inductive case (define-struct Visitor (fBase fInduct)) ;; execute: list-of-any1 Visitor any2 --> any3 ;; Executes ("accepts") the visitor on the list ;; returning the result. ;; param is passed to the visitor unmodified. ;; The base case of the Visitor is called on the empty list: ;; Visitor-fBase: list-of-any1 any2 --> any3 ;; The inductive case is called on the non-empty list. ;; Visitor-fInduct: list-of-any1 any2 --> any3 (define (execute a-list visitor param) (cond [(empty? a-list) ((Visitor-fBase visitor) a-list param)] [(cons? a-list) ((Visitor-fInduct visitor) a-list param)])) #| ;; Visitor template using local ;; The general purpose of the visitor goes here. (define listVisitor (local [;; The contract for the base case function goes here ;; Any base-case specific purpose goes here. (define (fBase a-list param) (...a-list...param...)) ;; The contract for the inductive case function goes here ;; Any inductive-case specific purpose goes here. (define (fInduct a-list param) (...(first a-list)...(execute (rest a-list) listVisitor ...)))] (make-Visitor fBase fInduct))) |# #| ;; Visitor template, using lambda ;; The general purpose of the visitor goes here. (define listVisitor (make-Visitor ;; The contract for the base case function goes here ;; Any base-case specific purpose goes here. (lambda (a-list param) (...a-list...param...)) ;; The contract for the inductive case function goes here ;; Any inductive-case specific purpose goes here. (lambda (a-list param) (...(first a-list) (execute (rest a-list) listVisitor ...)... param...)))) |# ;; ordIns does an ordered insert of param into ;; an ascending list. (define ordIns (make-Visitor ;; empty num --> list-of-num ;; returns the param as a list. (lambda (a-list param) (cons param a-list)) ;; nowhere to put it except here ;; list-of-num num --> list-of-num ;; returns the list with the param inserted in its proper location (lambda (a-list param) (cond [(< param (first a-list)) (cons param a-list)] ;; put it here [else (cons (first a-list) (execute (rest a-list) ordIns param))])))) ;; keep looking "ordIns test case:" (equal? (list 1 2 3 4 5 6 7) (execute (list 1 2 3 5 6 7) ordIns 4)) ;; listSort sorts a list in ascending order ;; param is ignored. (define listSort (make-Visitor ;; empty any --> empty ;; empty list is already sorted. (lambda (a-list param) empty) ;; non-empty-list-of-num any --> non-empty-list-of-num ;; returns the sorted list (lambda (a-list param) (execute (execute (rest a-list) listSort param) ordIns (first a-list))))) "listSort test case:" (equal? (list 1 2 3 4 5 6 7) (execute (list 4 2 7 3 5 6 1) listSort null)) ;; mapVisitor implements map as a visitor ;; the parameter is a function of one variable (define mapVisitor (make-Visitor ;; empty (lambda: any1 --> any2) --> empty ;; base case is always empty (lambda (a-list func) empty) ;; non-empty-list-of-any1 (lambda: any1 --> any2) --> non-empty-list-of-any2 ;; applies func to every element of the list (lambda (a-list func) (cons (func (first a-list)) (execute (rest a-list) mapVisitor func))))) "mapVisitor test cases:" (equal? (map sqrt (list 1 4 9 16 25)) (execute (list 1 4 9 16 25) mapVisitor sqrt)) (equal? (map (lambda (x) (string-append (number->string x) " banana")) (list 1 2 3 4 5)) (execute (list 1 2 3 4 5) mapVisitor (lambda (x) (string-append (number->string x) " banana")))) ;; Structure used for both foldrList and foldlList ;; f is the inductive case function ;; base is the base case value. ;; If the input list is a list-of-any1 ;; and the base case value is an any2, then ;; the inductive case function has the abstract contract: ;; f: any1 any2 --> any2 (define-struct FoldInp (f base)) ;;foldrVisitor implements foldr as a visitor (define foldrVisitor (make-Visitor ;; empty FoldInp --> any2 ;; returns the base case value (lambda (a-list foldInp) (FoldInp-base foldInp)) ;; non-empty-list-of-any1 FoldInp --> any2 ;; applies the inductive case function to first and ;; the recursive result and returns the result. (lambda (a-list foldInp) ((FoldInp-f foldInp) (first a-list) (execute (rest a-list) foldrVisitor foldInp))))) "foldrVisitor test cases:" (equal? (foldr + 0 empty) (execute empty foldrVisitor (make-FoldInp + 0))) (equal? (foldr + 0 (list 1 2 3 4 5)) (execute (list 1 2 3 4 5) foldrVisitor (make-FoldInp + 0))) (equal? (foldr * 1 (list 1 2 3 4 5)) (execute (list 1 2 3 4 5) foldrVisitor (make-FoldInp * 1)))