;;;; -*- mode:Scheme -*- ;;;;

(load-option 'format)

(define rest cdr)

(define (map-non-false list fn)
  (if (null? list)
      '()
      (let ((answer (fn (first list))))
	(if answer
	    (cons answer (map-non-false (rest list) fn))
	    (map-non-false (rest list) fn)))))

(define (print x) (format #t "~s~%" x) x)

(define (remove-if predicate elements)
  "
  Purpose:	Remove all list elements that satisfy predicate
  "
  (cond ((null? elements) '())
	((predicate (first elements))
	 (remove-if predicate (rest elements)))
	(else
	 (cons (first elements)
	       (remove-if predicate (rest elements))))))

(define (remove-if-not predicate elements)
  "
  Purpose:	Remove all list elements that DO NOT satisfy predicate
  "
  (remove-if (lambda (x) (not (predicate x))) elements))

;;; Some auxiliary functions

;;; Finds the position (integer from 0) of item in the list.  The test
;;; is eq?.  If a third arg is provided then that function is applied
;;; to the list element before testing for equality.
;;; (position 'b '(a b c)) => 1
;;; (position 'b '((a 1) (b 2) (2 3)) first) => 1
(define (position item list . args)
  (let ((found #f)
	(key-fn
	 (if (null? args)
	     #f
	     (first args))))
    (do ((x list (rest x))
	 (i 0 (+ i 1)))
	((or (null? x) found))
      (if (eq? (if key-fn (key-fn (first x)) (first x)) item)
	  (set! found i)))
    found))

;;; Constructs a list of indices starting at 0 that goes up to n-1
;;; where n is the length of the list l.
;;; (index-list '(a b c)) => (0 1 2)
(define (index-list l)
  (define (index-list-aux l index)
    (if (null? l)
	'()
	(cons index (index-list-aux (rest l) (+ index 1)))))
  (index-list-aux l 0))

(define (make-index-list n)
  (define (make-index-list-aux i)
    (if (< i n) 
	(cons i (make-index-list-aux (+ 1 i)))
	'()))
  (make-index-list-aux 0))

(define (random-list-entry l)
  (if (null? l)
      (error 'random-index "called with empty list")
      (list-ref l (random (length l)))))

