// The higher order functions for lists

// AUTHOR: Gary T. Leavens
// see the included file for details.

#include "CookList.h"

template <class T>
void List_for_each<T>::for_each
                (const List<T>& lst) {
  const List<T> *it = &lst;
  while (!(it->is_null())) {
    the_proc(it->head());
    it = it->tail();
  }
}


template <class T, class S>
List<S>* List_map<T,S>::map
                (const List<T>& lst) {
  if (lst.is_null()) {
    return new Nil<S>();
  } else {
    return new Cons<S>
      (the_proc(lst.head()),
       map(*(lst.tail())));
  }
}


template <class T, class S>
S List_flat_recur<T,S>::flat_recur
                (const List<T>& lst) {
  if (lst.is_null()) {
    return seed();
  } else {
    return the_proc
      (lst.head(),
       flat_recur(*(lst.tail())));
  }
}


// The following class is only used
// in the implementation of operator <<
template <class T>
/* static */
class print_it_closure
  : public List_for_each<T> {
public:
  print_it_closure(ostream & out)
    : rep(out) {}
  void the_proc(T x) {
    rep << " " << x;
  }
private:
  ostream& rep;
};

template <class T>
ostream& operator << (ostream & out,
		      const List<T>& lst){
    out << "(";
    if (~(lst.is_null())) {
      out << lst.head();
      print_it_closure<T>(out).for_each
	(*(lst.tail()));
    };
    out << ")";
  return out;
}
