#ifndef __LIST_H__ #define __LIST_H__ #include "lazy.h" // #include "functional.h" #include #include class EmptyList : std::exception { }; template class List { public: typedef T list_item_type; List() { } virtual ~List() { } virtual Lazy getHead() = 0; virtual Lazy< List > getTail() = 0; virtual bool isEmpty() = 0; }; template using LazyList = R>, true>; template class Cons : public List { public: typedef T list_item_type; Cons(Lazy head, LazyList tail) : List(), head(head), tail(tail) { } virtual ~Cons() { } virtual Lazy getHead() { return head; } virtual LazyList getTail() { return tail; } virtual bool isEmpty() { return false; } private: Lazy head; LazyList tail; }; template class Nil : public List { public: typedef T list_item_type; Nil() : List() { } virtual ~Nil() { } virtual Lazy getHead() { throw EmptyList(); } virtual LazyList getTail() { throw EmptyList(); } virtual bool isEmpty() { return true; } static LazyList instance; private: static LazyList initInstance(); }; template LazyList Nil::instance = Nil::initInstance(); template LazyList Nil::initInstance() { auto rNil = Ref::mk>(); return suspend(rNil); } template LazyList cons(Lazy head, LazyList tail) { return suspend> (Ref::mk> (head, tail)); } template inline LazyList operator<<=(Lazy head, LazyList tail) { return cons(head, tail); } /*template class LLIterator { public: LLIterator(LazyList list) : list(list) { } T& operator *() { return lazyVal(head(list)).deref(); } LLIterator& operator++() { list = tail(list); } private: LazyList list; };*/ template LazyList drop(LazyList list, Int i) { if (i == 0L) { return list; } else { return drop(list.tail(), i - 1L); } } /**** iterate ****/ template LazyList iterate(Delegate1, LazyBase> fun, Lazy init) { return mkLazy(mkLFun([] (decltype(fun) fun, decltype(init) init) { return Ref::mk> (init, iterate (fun, fun(init))); }, fun, init)); } /**** map ****/ template LazyList map(Delegate1< LazyBase, LazyBase > fun, LazyList l) { return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l) l) { return Ref::mk> (fun(l.head()), map(fun, l.tail())); }, fun, l)); } /**** filter ****/ template LazyList filter(Delegate1> fun, LazyList l) { return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l) l) { auto lx = l; while (*fun(lx.head()) == false) { lx = lx.tail(); } return Ref::mk> (lx.head(), filter(fun, lx.tail())); }, fun, l)); } /**** zipWith ****/ template // TODO allow different lists LazyList zipWith(Delegate2, LazyBase, LazyBase> fun, LazyList l1, LazyList l2) { return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l1) l1, decltype(l2) l2) { return Ref::mk> (fun(l1.head(), l2.head()), zipWith(fun, l1.tail(), l2.tail())); }, fun, l1, l2)); } /**** specialization ****/ template class R>, true> : public R>, false> { protected: // passing protected constructor inline R(int i) : R>, false>(i) { } public: inline R() : R>, false>() { } template inline R(R, od>& o) : R>, false>(o, 0) { _assert_subclass> ERRORList; _assert_subclass ERRORItem; } template inline R(R, od>&& o) : R>, false>(o, 0) { _assert_subclass> ERRORList; _assert_subclass ERRORItem; } // passing operator= template inline R>, true>& operator=(R, od>& o) { _assert_subclass> ERRORList; _assert_subclass ERRORItem; R>, false>::copy(o); return *this; } template inline R>, true>& operator=(R, od>&& o) { _assert_subclass> ERRORList; _assert_subclass ERRORItem; R>, false>::copy(o); return *this; } // additional functionality inline Lazy head() { return this->deref().get().deref().getHead(); } inline LazyList tail() { return this->deref().get().deref().getTail(); } inline static LazyList iterate(Delegate1, LazyBase> fun, Lazy init) { return ::iterate(fun, init); } inline static LazyList iterate(Delegate1, LazyBase> fun, T init) { return ::iterate(fun, suspend(init)); } template inline LazyList map(Delegate1, LazyBase> fun) { return ::map(fun, *this); } inline LazyList filter(Delegate1> fun) { return ::filter(fun, *this); } inline LazyList drop(Int i) { return ::drop(*this, i); } // keep reference makeable with Ref::mk friend Ref; }; #endif