• 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 ,郁闷死了,我说怎么取第二个值了。

  • 相关阅读:
    行业动态 | Instagram: 从Redis到Cassandra成功节省75%的成本
    技术基础 | 有关K8ssandra的那些事儿
    技术基础 | 重要指标和告警
    Cassandra与职业发展 | 阿里云栾小凡 × 蔚来汽车张旭东 × 网龙阙乃祯
    Cassandra与Kubernetes
    为何选择云原生?
    区分NoSQL数据库
    什么是NoSQL
    JMeter学习(一)JMeter的安装和目录解析
    CentOS 7 nfs客户端挂载问题
  • 原文地址:https://www.cnblogs.com/bigben0123/p/16221533.html
Copyright © 2020-2023  润新知