c++函數式編程 筆記

函數可以看作是一個普通變量。可被存儲在集合或結構中,作爲參數傳遞給其他函數,或作爲函數的返回值。
高階函數:能夠接收函數作爲參數或者返回函數作爲結果的函數。

  • filter:過濾後集合類型不變
    一個類型:T
    包含T類型的集合:Collection<T> or C<T>
    filter函數原型就可以寫作:

(Collection<T>, (T->bool)) **->** Collection<T>

"->"符號後面是返回值類型`

  • map/transform: 返回值可以是其他類型,所以名字叫變形呢
    (Collection<In>, (In->Out)) -> Collection<Out>

累加器 std::accumulate/ folding/ reducing: 對遞歸結構(vector,list,tree...)遍歷,並逐步構建自己需要的結果。
(std::reduce可實現並行效果)
摺疊接收集合包含T類型條目,R類型的初始值和一個函數f:(R,T)->R

過濾函數區別

filer 是對T返回bool;
transform 對T返回另外一種類型 "T1";
accumulate 對 上次結果R和T 返回 上次結果R。R可以是個集合,實現蒐集。

循環與遞歸

純FP不存在循環,用遞歸實現。思想是,對於一個集合,遞歸地處理它的頭(第一個元素)和尾(其他所有元素),這又可以看作集合。
分別對頭和尾做處理。尾就又遞歸調用自身處理。
其實 accumulate 就是遍歷元素的很好方法。將返回可以全部放到新的集合中。

std::accumulate 實現原理 與 demo

實現:

template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
    for (; first != last; ++first) {
        init = std::move(init) + *first; // std::move since C++20
    }
    return init;
}

template<class InputIt, class T, class BinaryOperation>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init, 
             BinaryOperation op)
{
    for (; first != last; ++first) {
        init = op(std::move(init), *first); // std::move since C++20
    }
    return init;
}

demo:

    const std::vector<int> ds = { 1, 2, 3 };
    int n = std::accumulate(ds.begin(), ds.end(),
        0,
        [](int a, int d) { 
            cout << a << " " << d << endl;
            return a * 10 + d; 
        
        });
    std::cout << n << std::endl;

    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 
    int sum = std::accumulate(v.begin(), v.end(), 0);
 
    int product = std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
 
    auto dash_fold = [](std::string a, int b) {
                         return std::move(a) + '-' + std::to_string(b);
                     };
 
    std::string s = std::accumulate(std::next(v.begin()), v.end(),
                                    std::to_string(v[0]), // start with first element
                                    dash_fold);
 
    // Right fold using reverse iterators
    std::string rs = std::accumulate(std::next(v.rbegin()), v.rend(),
                                     std::to_string(v.back()), // start with last element
                                     dash_fold);
 
    std::cout << "sum: " << sum << '\n'
              << "product: " << product << '\n'
              << "dash-separated string: " << s << '\n'
              << "dash-separated string (right-folded): " << rs << '\n';

注意 std::next ,鬱悶死了,我說怎麼取第二個值了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章