c++ 函數式

用了一段時間的函數式語言像erlang、mathematica,經過fold,map,filter等高階函數來編程確有好處。c++

  1. 可靠。 每一個函數都只涉及其必須的變量,避免了使用指針和無關量。正所謂nocode is the best code.
  2. 簡潔。 少些了一堆遍歷的通用代碼,確實能減小一些重複代碼。
  3. 邏輯。 fold 包含了遞推的邏輯。filter能夠認爲是取子集。所以運用高階函數能夠找到對應的數學邏輯,這樣的代碼更加地嚴謹富有邏輯。我比較推崇《算法概論》,相比《算法導論》,前者更加註重數學邏輯。一旦具有了嚴謹的數學邏輯,那麼也就是說咱們能夠證實咱們的代碼是沒有BUG的。這大概就是咱們程序員的終極目標了!

固然也有它的缺點。程序員

  1. 代碼寫的慢了。 常常停下來想該怎麼寫。
  2. 並非全部地方都好用。 C/C++對這方面的支持比較差。

因而我寫了一個擴展類,來使得STL容器具有高階函數。 默認將結果保存到本容器。算法

template<class Collection>
class FP : public Collection {
public:
    template<typename T>
    FP(std::initializer_list<T> list):Collection(list) {}

    template<typename ...Args>
    explicit FP(Args... args) {
        Collection(args...);
    }

    explicit FP(Collection &c) : Collection(c) {}

    template<typename unop>
    FP<Collection> each(unop op) {
        std::for_each(this->begin(), this->end(), op);
        return *this;
    }

    template<typename unop>
    FP<Collection> map(unop op) {
        std::transform(this->begin(), this->end(), this->begin(), op);
        return *this;
    }

    template<typename unop,class ...C>
    FP<Collection> thread(unop op,C... c) {
        this->clear();
        const size_t size=get_size(c...);
        for(int i=0;i<size;i++)
            this->push_back(apply_from_tuple(op,value_tuple(i,c...)));
        return *this;
    }
    template<typename TResult, typename F>
    TResult fold(const TResult &startValue, const F &f) {
        TResult result = startValue;
        auto p = this->begin();
        while (p != this->end())
            result = f(result, *p++);
        return result;
    }

    template< typename F>
    auto reduce(const F &f) {
        auto p = this->begin();
        auto result=*p++;
        while (p != this->end())
            result = f(result,*p++ );
        return result;
    }

    template<typename binop>
    FP<Collection> zip(Collection fc, Collection sc, binop op) {
        std::transform(fc.begin(), fc.end(), sc.begin(), fc.begin(), op);
        Collection::assign(fc.begin(), fc.end());
        return *this;
    }

    template<typename Condition>
    bool exists(Condition con) {
        auto exist = std::find_if(this->begin(), this->end(), con);
        return exist != this->end();
    }


    template<typename Predicate>
    Collection filterNot(Predicate predicate) {
        auto returnIterator = std::remove_if(this->begin(), this->end(), predicate);
        this->erase(returnIterator, std::end(this));
        return *this;
    }
};

example:編程

int main() {
     FP<vector<int>> v1{1,2,3,4,5};
    funt(v1);
    cout<<"list : ";
    for(auto p:v1)
        cout<<" "<<p;
    cout<<endl;

    int sum=v1.reduce([](int a,int b){return a+b;});
    cout<<"sum : "<<sum<<endl;

    FP<vector<int>> v2=v1;

    cout<<"map i*i : ";
    v1.map([](int i){return i*i;}).each([](int i){
        cout<<i<<" ";
    });
    cout<<endl;


    cout<<"thread: ";
    v2.thread([](int a,int b){return a-b;},v1,v2).each([](int i){
        cout<<i<<" ";
    });
    cout<<endl;

    //對map容器操做
    FP<std::map<int,float>> m;
    for(auto i:v2)
        m[i]=i*i;
    print(m);
    m.each([](std::pair<const int,float>& it){
        it.second+=0.2;});
    cout<<"操做後"<<endl;
    print(m);

    return 0;
}

在C++中使用函數式還要考慮內存分配問題。畢竟語言支持不太好,在正式環境下仍是避免使用的好。使用標準的STL transform 很大程度上也能夠實現一些功能。app

thread

這個操做通常的函數式語言是沒有的,這個是從mathematica上學到的。它將多個大小相同的集合用函數op組合在一塊兒,相似與ZIP操做,但zip只能處理2組容器,而thread能夠處理任意個。函數

參考

c++函數式post

相關文章
相關標籤/搜索