/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* $Rev$ $Date$ */ #ifndef tuscany_list_hpp #define tuscany_list_hpp /** * Simple list functions. */ #include #include "function.hpp" namespace tuscany { long countlists = 0; long countIlists = 0; long countClists = 0; long countElists = 0; bool resetListCounters() { countlists = countIlists = countClists = countElists = 0; return true; } bool printListCounters() { std::cout << "countlists " << countlists << std::endl; std::cout << "countElists " << countElists << std::endl; std::cout << "countIlists " << countIlists << std::endl; std::cout << "countClists " << countClists << std::endl; return true; } /** * A car/cdr lisp-like pair, base structure to construct lists. */ template class list { public: list() { countlists++; countElists++; } list(const T car, const lambda ()>& cdr) : car(car), cdr(cdr) { countlists++; countIlists++; } list(const list& p) : car(p.car), cdr(p.cdr) { countlists++; countClists++; } const list& operator=(const list& p) { if(this == &p) return *this; car = p.car; cdr = p.cdr; return *this; } ~list() { countlists--; } const bool operator==(const list& p) const { if(this == &p) return true; if(isNil(cdr)) return isNil(p.cdr); if(isNil(p.cdr)) return false; if(!(car == p.car)) return false; if(cdr == p.cdr) return true; return cdr() == p.cdr(); } const bool operator!=(const list& p) const { return !this->operator==(p); } operator const list >() const { return (list >)T(*this); } list& operator<<(const T& v) { *this = append(*this, mklist(v)); return *this; } template friend const bool isNil(const list& p); template friend const X car(const list& p); template friend const list cdr(const list& p); template friend const bool setCar(list& p, const X& car); template friend const bool setCdr(list& p, const list& cdr); template friend const bool setCdr(list& p, const lambda ()>& cdr); private: T car; lambda ()> cdr; }; /** * Returns true if the given list is nil. */ template const bool isNil(const list& p) { return isNil(p.cdr); } /** * Write a list to an output stream. */ template std::ostream& operator<<(std::ostream& out, const list& l) { if(isNil(l)) return out << "()"; out << "("; list ml = l; while(true) { out << car(ml); ml = cdr(ml); if (isNil(ml)) break; out << " "; } return out << ")"; } /** * Construct a (lazy) list from a value and a lambda function that returns the cdr. */ template const list cons(const T& car, const lambda ()>& cdr) { return list (car, cdr); } /** * Construct a list from a value and a cdr list. */ template const list cons(const T& car, const list& cdr) { return list (car, result(cdr)); } /** * Cons variations for use with the reduce and reduceRight functions. */ template const list lcons(const list& cdr, const T& car) { return cons(car, cdr); } template const list rcons(const T& car, const list& cdr) { return cons(car, cdr); } /** * Construct a list of one value. */ template const list mklist(const T& car) { return list (car, result(list ())); } /** * Construct a list of two values. */ template const list mklist(const T& a, const T& b) { return cons(a, mklist(b)); } /** * Construct a list of three values. */ template const list mklist(const T& a, const T& b, const T& c) { return cons(a, cons(b, mklist(c))); } /** * Construct a list of four values. */ template const list mklist(const T& a, const T& b, const T& c, const T& d) { return cons(a, cons(b, cons(c, mklist(d)))); } /** * Construct a list of five values. */ template const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { return cons(a, cons(b, cons(c, cons(d, mklist(e))))); } /** * Construct a list of six values. */ template const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f)))))); } /** * Returns the car of a list. */ template const T car(const list& p) { return p.car; } /** * Returns the cdr of a list. */ template const list cdr(const list& p) { return p.cdr(); } /** * Sets the car of a list. */ template const bool setCar(list& p, const T& car) { p.car = car; return true; } /** * Sets the cdr of a list. */ template const bool setCdr(list& p, const list& c) { p.cdr = result(c); return true; } /** * Sets the cdr of a list to a lambda function. */ template const bool setCdr(list& p, const lambda ()>& cdr) { p.cdr = cdr; return true; } /** * Returns the car of the cdr of a list. */ template const T cadr(const list& p) { return car(cdr(p)); } /** * Returns the car of the cdr of the cdr of a list. */ template const T caddr(const list& p) { return car(cdr(cdr(p))); } /** * Returns the cdr of a cdr of a list. */ template const list cddr(const list& p) { return cdr(cdr(p)); } /** * Returns the cdr of a cdr of the cdr of a list. */ template const list cdddr(const list& p) { return cdr(cdr(cdr(p))); } /** * Returns the length of a list. */ template struct lengthRef { const int operator()(const int c, const list& p) { if(isNil(p)) return c; return (*this)(c + 1, cdr(p)); } }; template const int length(const list& p) { return lengthRef ()(0, p); } /** * Appends a list and a lambda function returning a list. */ template struct appendCdr { const list a; const lambda ()> fb; appendCdr(const list& a, const lambda ()>& fb) : a(a), fb(fb) { } const list operator()() const { return append(a, fb); } }; template const list append(const list&a, const lambda ()>& fb) { if(isNil(a)) return fb(); return cons(car(a), appendCdr (cdr(a), fb)); } /** * Appends two lists. */ template const list append(const list&a, const list& b) { return append(a, result(b)); } /** * Map a lambda function on a list. */ template const list map(const lambda& f, const list& p) { if(isNil(p)) return list (); return cons(f(car(p)), map(f, cdr(p))); } /** * Run a reduce lambda function on a list. */ template struct reduceAccumulate { const lambda f; reduceAccumulate(const lambda& f) : f(f) { } R operator()(const R& acc, const list& p) const { if(isNil(p)) return acc; return (*this)(f(acc, car(p)), cdr(p)); } }; template const R reduce(const lambda& f, const R& initial, const list& p) { return reduceAccumulate (f)(initial, p); } template struct reduceRightAccumulate { const lambda f; reduceRightAccumulate(const lambda& f) : f(f) { } R operator()(const list& p, const R& acc) const { if(isNil(p)) return acc; return (*this)(cdr(p), f(car(p), acc)); } }; template const R reduceRight(const lambda& f, const R& initial, const list& p) { return reduceRightAccumulate (f)(p, initial); } /** * Run a filter lambda function on a list. */ template const list filter(const lambda& f, const list& p) { if(isNil(p)) return list (); if(f(car(p))) { const lambda (lambda , list )> ff(filter ); return cons(car(p), curry(ff, f, cdr(p))); } return filter(f, cdr(p)); } /** * Returns a list pointing to a member of a list. */ template const list member(const T& t, const list& p) { if(isNil(p)) return list (); if(t == car(p)) return p; return member(t, cdr(p)); } /** * Reverse a list. */ template const list reverseIter(const list& acc, const list& p) { if(isNil(p)) return acc; return reverseIter(cons(car(p), acc), cdr(p)); } template const list reverse(const list& p) { return reverseIter(list (), p); } template const list seq(const T& start, const T& end); template struct seqGenerate { const T start; const T end; seqGenerate(const T& start, const T&end) : start(start), end(end) { } const list operator()() const { return seq (start, end); } }; /** * Returns a sequence of values between the given bounds. */ template const list seq(const T& start, const T& end) { if(start == end) return mklist(start); if(start < end) return cons(start, seqGenerate (start + 1, end)); return cons(start, seqGenerate (start - 1, end)); } /** * Returns the i-th element of a list. */ template const T listRef(const list& l, const int i) { if (i == 0) return car(l); return listRef(cdr(l), i - 1); } /** * Returns the first pair matching a key from a list of key value pairs. */ template const list assoc(const T& k, const list >& p) { if(isNil(p)) return list (); if(k == car(car(p))) return car(p); return assoc(k, cdr(p)); } /** * Returns a list of lists containing elements from two input lists. */ template const list > zip(const list& a, const list& b) { if (isNil(a) || isNil(b)) return list >(); return cons >(mklist(car(a), car(b)), zip(cdr(a), cdr(b))); } /** * Converts a list of key value pairs to a list containing the list of keys and the list of values. */ template const list unzipKeys(const list >& l) { if (isNil(l)) return list(); return cons(car(car(l)), unzipKeys(cdr(l))); } template const list unzipValues(const list >& l) { if (isNil(l)) return list(); return cons(cadr(car(l)), unzipValues(cdr(l))); } template const list > unzip(const list >& l) { return mklist >(unzipKeys(l), unzipValues(l)); } } #endif /* tuscany_list_hpp */