source: liblaziness/list.h @ 13

Last change on this file since 13 was 4, checked in by artyom, 13 years ago

liblaziness

File size: 5.3 KB
Line 
1#ifndef __LIST_H__
2#define __LIST_H__
3#include "lazy.h"
4// #include "functional.h"
5#include <exception>
6#include <iostream>
7
8class EmptyList : std::exception { };
9
10template <typename T>
11class List
12{
13        public:
14                typedef T list_item_type;
15                List() { }
16                virtual ~List() { }
17                virtual Lazy<T> getHead() = 0;
18                virtual Lazy< List<T> > getTail() = 0;
19                virtual bool isEmpty() = 0;
20};
21
22template <typename T>
23using LazyList = R<LazyBase<List<T>>, true>;
24
25template <typename T>
26class Cons : public List<T>
27{
28        public:
29                typedef T list_item_type;
30                Cons(Lazy<T> head, LazyList<T> tail) : List<T>(), head(head), tail(tail) { }
31                virtual ~Cons() { }
32                virtual Lazy<T> getHead() { return head; }
33                virtual LazyList<T> getTail() { return tail; }
34                virtual bool isEmpty() { return false; }
35        private:
36                Lazy<T> head;
37                LazyList<T> tail;
38};
39
40template <typename T>
41class Nil : public List<T>
42{
43        public:
44                typedef T list_item_type;
45                Nil() : List<T>() { }
46                virtual ~Nil() { }
47                virtual Lazy<T> getHead() { throw EmptyList(); }
48                virtual LazyList<T> getTail() { throw EmptyList(); }
49                virtual bool isEmpty() { return true; }
50
51                static LazyList<T> instance;
52        private:
53                static LazyList<T> initInstance();
54};
55
56template<typename T>
57LazyList<T> Nil<T>::instance = Nil<T>::initInstance();
58
59template<typename T>
60LazyList<T> Nil<T>::initInstance()
61{
62        auto rNil = Ref::mk<Nil<T>>();
63        return suspend(rNil);
64}
65
66template <typename T>
67LazyList<T> cons(Lazy<T> head, LazyList<T> tail)
68{
69        return suspend<List<T>> (Ref::mk<Cons<T>> (head, tail));
70}
71
72template <typename T>
73inline LazyList<T> operator<<=(Lazy<T> head, LazyList<T> tail)
74{
75        return cons(head, tail);
76}
77
78/*template <typename T>
79class LLIterator
80{
81        public:
82                LLIterator(LazyList<T> list) : list(list) { }
83                T& operator *()
84                {
85                        return lazyVal(head(list)).deref();
86                }
87                LLIterator& operator++()
88                {
89                        list = tail(list);
90                }
91        private:
92                LazyList<T> list;
93};*/
94
95template <typename T>
96LazyList<T> drop(LazyList<T> list, Int i)
97{
98        if (i == 0L)
99        {
100                return list;
101        }
102        else
103        {
104                return drop(list.tail(), i - 1L);
105        }
106}
107
108/**** iterate ****/
109
110template <typename T>
111LazyList<T> iterate(Delegate1<LazyBase<T>, LazyBase<T>> fun, Lazy<T> init)
112{
113        return mkLazy(mkLFun([] (decltype(fun) fun, decltype(init) init) {
114                return Ref::mk<Cons<T>> (init, iterate (fun, fun(init)));
115        }, fun, init));
116}
117
118/**** map ****/
119
120template <typename TSource, typename TDest>
121LazyList<TDest> map(Delegate1< LazyBase<TDest>, LazyBase<TSource> > fun, LazyList<TSource> l)
122{
123        return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l) l) {
124                return Ref::mk<Cons<TDest>> (fun(l.head()), map(fun, l.tail()));
125        }, fun, l));
126}
127
128/**** filter ****/
129template <typename T>
130LazyList<T> filter(Delegate1<bool, LazyBase<T>> fun, LazyList<T> l)
131{
132        return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l) l) {
133                auto lx = l;
134                while (*fun(lx.head()) == false)
135                {
136                        lx = lx.tail();
137                }
138                return Ref::mk<Cons<T>> (lx.head(), filter(fun, lx.tail()));
139        }, fun, l));
140}
141
142/**** zipWith ****/
143
144template <typename T> // TODO allow different lists
145LazyList<T> zipWith(Delegate2<LazyBase<T>, LazyBase<T>, LazyBase<T>> fun, LazyList<T> l1, LazyList<T> l2)
146{
147        return mkLazy(mkLFun([] (decltype(fun) fun, decltype(l1) l1, decltype(l2) l2) {
148                return Ref::mk<Cons<T>> (fun(l1.head(), l2.head()), zipWith(fun, l1.tail(), l2.tail()));
149        }, fun, l1, l2));
150}
151
152/**** specialization ****/
153template <typename T>
154class R<LazyBase<List<T>>, true> : public R<LazyBase<List<T>>, false>
155{
156        protected:
157                // passing protected constructor
158                inline R(int i) : R<LazyBase<List<T>>, false>(i) { }
159        public:
160                inline R() : R<LazyBase<List<T>>, false>() { }
161                template<typename U, bool od> inline R(R<LazyBase<U>, od>&  o) : R<LazyBase<List<T>>, false>(o, 0)
162                {
163                        _assert_subclass<U, List<typename U::list_item_type>> ERRORList;
164                        _assert_subclass<typename U::list_item_type, T> ERRORItem;
165                }
166                template<typename U, bool od> inline R(R<LazyBase<U>, od>&& o) : R<LazyBase<List<T>>, false>(o, 0)
167                {
168                        _assert_subclass<U, List<typename U::list_item_type>> ERRORList;
169                        _assert_subclass<typename U::list_item_type, T> ERRORItem;
170                }
171                // passing operator=
172                template<typename U, bool od> inline R<LazyBase<List<T>>, true>& operator=(R<LazyBase<U>, od>&  o)
173                {
174                        _assert_subclass<U, List<typename U::list_item_type>> ERRORList;
175                        _assert_subclass<typename U::list_item_type, T> ERRORItem;
176                        R<LazyBase<List<T>>, false>::copy(o);
177                        return *this;
178                }
179                template<typename U, bool od> inline R<LazyBase<List<T>>, true>& operator=(R<LazyBase<U>, od>&& o)
180                {
181                        _assert_subclass<U, List<typename U::list_item_type>> ERRORList;
182                        _assert_subclass<typename U::list_item_type, T> ERRORItem;
183                        R<LazyBase<List<T>>, false>::copy(o);
184                        return *this;
185                }
186                // additional functionality
187                inline Lazy<T>     head() { return this->deref().get().deref().getHead(); }
188                inline LazyList<T> tail() { return this->deref().get().deref().getTail(); }
189                inline static LazyList<T> iterate(Delegate1<LazyBase<T>, LazyBase<T>> fun, Lazy<T> init) { return ::iterate(fun, init); }
190                inline static LazyList<T> iterate(Delegate1<LazyBase<T>, LazyBase<T>> fun, T init) { return ::iterate(fun, suspend(init)); }
191                template<typename U> inline LazyList<U> map(Delegate1<LazyBase<U>, LazyBase<T>> fun) { return ::map(fun, *this); }
192                inline LazyList<T> filter(Delegate1<bool, LazyBase<T>> fun) { return ::filter(fun, *this); }
193                inline LazyList<T> drop(Int i) { return ::drop(*this, i); }
194                // keep reference makeable with Ref::mk
195                friend Ref;
196};
197
198#endif
Note: See TracBrowser for help on using the repository browser.