 					(load module) ) ) ) ) )	; module can pull features off loading list
 
 (defun ngender-require (module &rest features)
-	(unless (assq module *ngender-modules-loaded*)
-		(apply ngender-load (cons module features)) ) )
+	"load module with required features unless already done - used by macro ngender - order of features matters"
+	(if-let ( (module (ngender-normalize-module module)) )
+		(let ( (features (seq-filter #'consp (mapcar #'ngender-normalize-feature features))) )
+			(unless (member (cons module features) *ngender-modules-loaded*)
+				(apply #'ngender-load (cons module features)) ) ) ) )
 
 (defmacro ngender (&rest module+features)
 	(cons 'ngender-require (mapcar (lambda (x) (list 'quote x)) module+features)) )
 
+;; (macroexpand-1 '(ngender foo))
+;; (macroexpand-1 '(ngender foo this that))
+
 (defmacro ngender-provide (module)
-	(list 'ngender-provide (list 'quote module)) )
+	(list 'ngender-provide-function (list 'quote module)) )
+
+;; (macroexpand-1 '(ngender-provide foo))
+
+(defmacro ngender-forget (module)
+	"fagedaboutit"
+	(if-let ( (module (ngender-normalize-module module)) )
+		`(progn
+			 (ngender-forget-loading ,module)
+			 (ngender-forget-loaded ,module) )
+		`(ngender-warn 'module "a module name") ) )
+
+;; (macroexpand-1 '(ngender-forget foo))
 
 ;; ** Provide
 

				nil
				(if is-list (cons name url) pair) ) ) ) )

(defun ngender-add-package-archive-pair (symbol new-pair)
	(let* ( (key (car new-pair)) (alist (symbol-value symbol)) (old-pair (assoc key alist)) )
		(if (equal old-pair new-pair) t
			(when old-pair
				(lwarn "changing url for %s from %s to %s in %s" key (cdr old-pair) (cdr new-pair) symbol)
				(set symbol (assoc-delete-all key alist)) )
			(set symbol (cons new-pair (symbol-value symbol))) ) ) )

(defun ngender-add-package-archive-by-key (key)
	(let ( (pair (assoc key *ngender-known-package-archives*)) )
		(cond
			( (symbolp key) (ngender-package-archive-by-key (symbol-name key)) )
			( (not (stringp key)) (lwarn "expected string archive key: %s" key) )
			( (null pair) (lwarn "expected known archive key: %s" key) )
			( t (ngender-add-package-archive-pair 'package-archives pair) ) ) ) )

;; We're loading, push us on the stack!
(setq *ngender-modules-loading* (cons (list 'ngender) *ngender-modules-loading*))

;; should we warn if argument has an extension??
(defun ngender-normalize-module (x)
	"a module name is a filename string w/o extensions; we allow some substitutes"
	(ngender-a-string x) )

(defun ngender-normalize-feature (x)
	"a feature is a list whose first element is a symbol; we allow some substitutes"
	(let ( (warning (lambda (x) (ngender-warn x "feature"))) )
		(cond
			( (consp x)
				(let ( (head (car x)) )
					(cond
						( (eq 'quote head) (ngender-normalize-feature (cadr x)) )
						( (symbolp head) x )
						( (stringp head) (cons (intern head) (cdr x)) )
						( t (funcall warning x) nil ) ) ) )
			( (symbolp x) (list x) )
			( (stringp x) (funcall warning x) (list (intern x)) )
			( t (funcall warning x) nil) ) ) )

;; (mapcar #'ngender-normalize-feature
;;  '(foo "foo" 'foo ("foo" bar) '("foo" bar)) )

(defun ngender-forget-loading (module)
	"remove all instances of given module from list of modules in process of loading"
	(if-let ( (module (ngender-normalize-module module)) )
		(setq *ngender-modules-loading* (assoc-delete-all module *ngender-modules-loading*) ) ) )

(defun ngender-forget-loaded (module)
	"remove all instances of given module from list of modules already loaded"
	(if-let ( (module (ngender-normalize-module module)) )
		(setq *ngender-modules-loaded* (assoc-delete-all module *ngender-modules-loaded*)) ) )

(defun ngender-loading (module)
	"return the (module feature...) list requested for the given module being loaded"
	(if-let ( (module (ngender-normalize-module module)) )
		(assoc module *ngender-modules-loading*) ) )

(defmacro ngender-features (module)
	"provide just the feature list, leaving off the module name"
	`(cdr (ngender-loading ,(ngender-normalize-module module))) )

;; (macroexpand-1 '(ngender-features foo))
		
(defun ngender-provide-function (module)
	"move (module feature...) from loading to loaded - used by macro ngender-provide"
	(if-let ( (module (ngender-normalize-module module)) )
		(if-let ( (module+features (assoc module *ngender-modules-loading*)) )
			(progn
				(setq *ngender-modules-loading* (cl-delete module+features *ngender-modules-loading*))
				(add-to-list '*ngender-modules-loaded* module+features) )
			(lwarn :warning "ngender-provide: no %s being loaded, doing nothing" module) ) ) )

;; file a bug with emacs in re the apparent dynamic binding
;; of free / global variables with let.  There needs to be
;; a clear way to do this so we won't be hit by software rot!!
(defun ngender-load (module &rest features)
	"show we are loading (module features...) and load module using our load path"
	(if-let ( (module (ngender-normalize-module module)) )
