现代C++实战30讲
吴咏炜
前 Intel 资深软件架构师
立即订阅
3787 人已学习
课程目录
已更新 20 讲 / 共 30 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | C++这么难,为什么我们还要用C++?
免费
课前必读 | 有关术语发音及环境要求
基础篇 (9讲)
01 | 堆、栈、RAII:C++里该如何管理资源?
02 | 自己动手,实现C++的智能指针
03 | 右值和移动究竟解决了什么问题?
04 | 容器汇编 I:比较简单的若干容器
05 | 容器汇编 II:需要函数对象的容器
06 | 异常:用还是不用,这是个问题
07 | 迭代器和好用的新for循环
08 | 易用性改进 I:自动类型推断和初始化
09 | 易用性改进 II:字面量、静态断言和成员函数说明符
提高篇 (9讲)
10 | 到底应不应该返回对象?
11 | Unicode:进入多文字支持的世界
12 | 编译期多态:泛型编程和模板入门
13 | 编译期能做些什么?一个完整的计算世界
14 | SFINAE:不是错误的替换失败是怎么回事?
15 | constexpr:一个常态的世界
16 | 函数对象和lambda:进入函数式编程
17 | 函数式编程:一种越来越流行的编程范式
18 | 应用可变模板和tuple的编译期技巧
现代C++实战30讲
登录|注册

17 | 函数式编程:一种越来越流行的编程范式

吴咏炜 2020-01-03
你好,我是吴咏炜。
上一讲我们初步介绍了函数对象和 lambda 表达式,今天我们来讲讲它们的主要用途——函数式编程。

一个小例子

按惯例,我们还是从一个例子开始。想一下,如果给定一组文件名,要求数一下文件里的总文本行数,你会怎么做?
我们先规定一下函数的原型:
int count_lines(const char** begin,
const char** end);
也就是说,我们期待接受两个 C 字符串的迭代器,用来遍历所有的文件名;返回值代表文件中的总行数。
要测试行为是否正常,我们需要一个很小的 main 函数:
int main(int argc,
const char** argv)
{
int total_lines = count_lines(
argv + 1, argv + argc);
cout << "Total lines: "
<< total_lines << endl;
}
最传统的命令式编程大概会这样写代码:
int count_file(const char* name)
{
int count = 0;
ifstream ifs(name);
string line;
for (;;) {
getline(ifs, line);
if (!ifs) {
break;
}
++count;
}
return count;
}
int count_lines(const char** begin,
const char** end)
{
int count = 0;
for (; begin != end; ++begin) {
count += count_file(*begin);
}
return count;
}
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《现代C++实战30讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(3)

  • 罗乾林
    参考 istream_line_reader 实现的,望老师斧正

    template<typename _InIt, typename _Fun>
    class filter_view {
    public:
    class iterator { // 实现 InputIterator
    public:

    using iterator_category = input_iterator_tag;
    using value_type = typename _InIt::value_type;
    using difference_type = typename _InIt::difference_type;
    using pointer = typename _InIt::pointer;
    using reference = value_type&;

    iterator(_InIt _First, _InIt _Last, _Fun f)
    :_First(_First), _Last(_Last), _fun(f) {
    ++(*this);
    }

    reference operator*() const noexcept { return *_Cur; }

    pointer operator->() const noexcept { return &(*_Cur); }

    iterator& operator++() {
    while (_First != _Last && !_fun(*_First)) {
    _First++;
    }
    _Cur = _First;
    if (_First != _Last) {
    _First++;
    }
    return *this;
    }

    iterator operator++(int) {
    iterator temp(*this);
    ++(*this);
    return temp;
    }

    bool operator==(const iterator& rhs)
    const noexcept
    {
    return _Cur == rhs._Cur;
    }
    bool operator!=(const iterator& rhs)
    const noexcept
    {
    return !operator==(rhs);
    }
    private:
    _InIt _First;
    _InIt _Last;
    _InIt _Cur;
    _Fun _fun;

    };

    filter_view(_InIt _First, _InIt _Last, _Fun f)
    :_First(_First), _Last(_Last), _fun(f) {

    }

    iterator begin() const noexcept {
    return iterator(_First, _Last, _fun);
    }

    iterator end() const noexcept {
    return iterator(_Last, _Last, _fun);
    }
    private:
    _InIt _First;
    _InIt _Last;
    _Fun _fun;
    };

    作者回复: OK,没啥大问题。

    代码风格要稍微说明一下。你似乎是模拟了库代码的风格,这还是有点风险的。在一般的用户代码里,不应该出现双下划线打头、或者下划线加大写字母打头的标识符——这是给系统保留的。

    详见:

    https://zh.cppreference.com/w/cpp/language/identifiers

    2020-01-03
    1
    2
  • 廖熊猫
    Y-Combinator主要用到了一个不动点理论,刘未鹏老师的《康托尔、哥德尔、图灵——永恒的金色对角线》这篇文章里面说的相对详细一些。玩过一段函数式...就只有haskell那段代码看懂了😂

    作者回复: Y Combinator 只是好玩展示一下,刺激一下大家的好奇心。要进一步了解,是需要看参考资料,或者其他中英文资料的。你说的这篇我之前没看过,内容也不错。

    2020-01-03
  • hello world
    请问老师,map和reduce.那是最新的语句吗?还是有第三方库?那个TBB?

    作者回复: map-reduce 是一种方法,已经有很久了。在 C++ 里的直接对应是 transform 和 accumulate。TBB 见参考资料 [7]。

    2020-01-03
收起评论
3
返回
顶部