UNB/ CS/ David Bremner/ teaching/ cs4613/ lectures/ lecture22/ list.rkt
#lang plai/gc2/mutator
(allocator-setup "generational.rkt" 512)

;; Originally by Yixi Zhang
(provide sort)
;; reverse : list -> list
(define (reverse l) (reverse1 empty l))
(define (reverse1 a l)
  (if (empty? l)
      a
      (reverse1 (cons (first l) a) (rest l))))
;; append : list list -> list
(define (append x y)
  (if (empty? x)
      y
      (cons (first x) (append (rest x) y))))
;; map : proc list -> list
(define (map f l)
  (if (empty? l)
      empty
      (cons (f (first l)) (map f (rest l)))))
;; filter : proc list -> list
(define (filter f l) (filter1 f l empty))
(define (filter1 f l result)
  (if (empty? l)
      (reverse result)
      (filter1 f (rest l) (if (f (first l)) (cons (first l) result) result))))
;; foldr : proc any/c list -> any/c
(define (foldr f init l)
  (if (empty? l)
      init
      (f (first l) (foldr f init (rest l)))))
;; memq : any/c list -> list/#f
(define (memq x l)
  (if (empty? l)
      #f
      (if (eq? x (first l)) l (memq x (rest l)))))
;; memf : proc list -> list/#f
(define (memf f l)
  (if (empty? l)
      #f
      (if (f (first l)) l (memf f (rest l)))))
;; for-each : proc list -> void
(define (for-each f l)
  (or (empty? l)
       (begin (f (first l))
             (for-each f (rest l)))))
;; sort : list proc -> list
(define (sort l less?)
  (let ([f (lambda (x) (less? x (first l)))])
    (if (empty? l)
        l
        (append (sort (filter f (rest l)) less?)
                (append (cons (first l) empty)
                        (sort (filter (lambda (x) (if (f x) #f #t)) (rest l)) less?))))))