;; -*- Scheme -*-
;;
;; $Id: avl-tree11.scm,v 1.1 1998/03/16 07:57:20 foner Exp $

;;-----------

(require 'avl-tree:merge-insert)
(require 'avl-tree:nil)

;;-----------

;;+doc
;; procedure: avl-tree:from-list
;; arguments: list unwrap-key <? if-duplicate[old new]
;; signature: forall a,b,c => [b] x (c -> a) x (a x a -> bool) x (b x b -> b)
;;                         -> avl-tree[a,b,c]
;;
;; Construct an AVL-TREE from LIST using <? as the ordering function.
;; IF-DUPLICATE is used to decide which node to insert in the case that
;; LIST contains duplicate elments.  It is always called with two arguments,
;; the OLD node and the NEW one in that order, and should return whichever
;; is to reside in the tree.
;;
;; Examples :-
;;
;; > (avl-tree:from-list '(1 2 3 1 4) (lambda (id) id) < (lambda (o n) n))
;;
;;   { 1 -> 1, 2 -> 2, 3 -> 3, 4 -> 4 }
;;
;; This creates a tree with elements where the key/data are synonymous.
;; Note that in the case of duplicate, the last element in the list is
;; taken (not that it is possible to tell this in this example) 
;;
;; > (avl-tree:from-list '(("phone" . 6270) ("fax" . 6280) ("phone" . 8066))
;;     car string<? (lambda (o n) o))
;;
;; { "phone" -> 6270, "fax" -> "6280" }
;;-doc

(define avl-tree:from-list
  (lambda (l uk <? if-dup)
    (let loop ((t avl-tree:nil) (l l))
      (let ((if-found (lambda (o) (if-dup o (car l))))
	    (if-not-found (lambda () (car l))))
	(if (null? l)
	    t
	    (loop (avl-tree:merge-insert t (uk (car l)) uk <? if-found if-not-found)
		  (cdr l)))))))

;; eof
