V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzxxisme
V2EX  ›  C++

迫于生计,分享一个自己的 C++ LINQ API 实现

  •  
  •   zzxxisme · 2021-08-03 00:30:57 +08:00 · 2377 次点击
    这是一个创建于 987 天前的主题,其中的信息可能已经有所发展或是发生改变。
    Coll ( https://github.com/zzxx-husky/coll )

    C++作为一门古老而又与时俱进的编程语言,直到 C++20 才有 Ranges 提供函数式编程(或者 LINQ API,数据流处理,Bash 的管道命令)的风格。除了 C++20 的 Ranges,也有很多其他人提供了自己对这类 API 的实现。目前我看到的这些实现,基本上是基于迭代器( iterator )或者生成器( generator )的原理来实现的,这些实现会在迭代器的处理以及数据传递上有性能开销(此话待验证)。

    我在 Coll 里面尝试一种不同的实现方式,简而言之,通过函数内联( function inline )或者函数嵌套的方式把不同的函数逻辑组装起来,避免数据在不同函数之间传递的开销。

    希望给点意见。

    也希望点个赞。
    6 条回复    2021-08-03 15:43:20 +08:00
    3dwelcome
        1
    3dwelcome  
       2021-08-03 00:43:10 +08:00
    看不懂,只能路过给点个赞了。
    3dwelcome
        2
    3dwelcome  
       2021-08-03 00:45:59 +08:00
    为了适应不同的场合,我也改了不少 C++语法,但是大部分都是类似 TS->JS 这种源代码翻译的模式。
    zzxxisme
        3
    zzxxisme  
    OP
       2021-08-03 03:07:42 +08:00 via Android
    @3dwelcome 谢谢!其实我做的也不是编程语言层面的东西。我用的也是 C++提供的语法,做一些 api 层面的东西,期望 api 可以想例如 scala 那样的 collection api 的函数式 api 好用,同时性能达到最好。
    c0xt30a
        4
    c0xt30a  
       2021-08-03 06:08:16 +08:00
    首星挽尊。
    另外,是 lazy 的么? 比如这样一个操作

    ```
    a_container_with_10000000000000000000000_elements | take_first(3) | max_reduce;
    ```
    是能算的么?
    zzxxisme
        5
    zzxxisme  
    OP
       2021-08-03 11:21:06 +08:00
    @c0xt30a 是 lazy 的。针对你的例子,
    1. 第一个遍历 container 的操作就是翻译成

    for (auto& i : container) {
    ...
    }

    2. 第二个 take_first(3)的操作是翻译成

    num = 3
    ...
    if (num-- != 0) {
    ...
    } else {
    break
    }
    ...

    3. 第三个 max_reduce 的操作就是翻译成

    max = std::nullopt
    ...
    if (!max || *max < x) {
    max = x
    }

    然后把所有逻辑嵌套起来之后,就是下面这样:

    num = 3
    max = std::nullopt
    for (auto& i : container) {
    if (num-- != 0) {
    if (!max || *max < i) {
    max = i
    }
    } else {
    break
    }
    }

    按照你的例子,我弄了一个新的 example ( https://github.com/zzxx-husky/coll/blob/master/examples/first_n_max.cpp )。虽然不是遍历一个 container,但是也是试图 生成 很多的整数。因为只需要从前 3 个里面找,所以最后其实只生成了 3 个整数。下面是在 WSL 上运行 3 次的结果。

    zzxx@zzxx:~/repos/coll/release | master
    $ time ./examples/FirstNMax
    Int 1 is 463223032
    Int 2 is 1934040530
    Int 3 is 897990617
    The max of the 3 ints is 1934040530

    real 0m0.010s
    user 0m0.000s
    sys 0m0.016s

    zzxx@zzxx:~/repos/coll/release | master
    $ time ./examples/FirstNMax
    Int 1 is 2009885599
    Int 2 is 491657854
    Int 3 is 58190656
    The max of the 3 ints is 2009885599

    real 0m0.010s
    user 0m0.000s
    sys 0m0.000s

    zzxx@zzxx:~/repos/coll/release | master
    $ time ./examples/FirstNMax
    Int 1 is 1704636435
    Int 2 is 1382089679
    Int 3 is 1782466259
    The max of the 3 ints is 1782466259

    real 0m0.010s
    user 0m0.000s
    sys 0m0.000s
    TimothyT
        6
    TimothyT  
       2021-08-03 15:43:20 +08:00 via iPhone   ❤️ 1
    帮顶,晚上回去 kk
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5532 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 08:37 · PVG 16:37 · LAX 01:37 · JFK 04:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.