是否存在与Functional Java类似/等效的C ++库?

时间:2012-02-24 23:44:39

标签: c++ boost functional-programming

是否有与优秀Functional Java library相似或等效的开源C ++库?

具体功能包括:

  • 迭代或类似的地图,折叠/缩小,过滤等
  • 选项类型
  • 不可变数据结构实现

(好奇心问道,离开C ++好几年了)

是的,传统上认为其中一些功能需要垃圾回收。但是,有了现代C ++特性和库,有没有人开始通过功能转换传递托管指针?

更新 为了清楚起见,我想知道有类似于Functional Java的东西,所以以下可能是典型的语法:

// assumptions:
//   * my_list is a standard library iterable of ints
//   * f is a function of int that returns a std::string
//   * p is a predicate of std::string returning bool
//   * head_opt returns an option type
stream(my_list).map(f).filter(p).head_opt.get_or_else("None")

这是Functional Java提供的习惯用语,相信我很容易习惯它......

3 个答案:

答案 0 :(得分:10)

正如@jalf所说,地图和折叠已经在标准中,隐藏在不同的名称背后:

  • 地图 - &gt; std::transform,位于标题<algorithm>
  • fold - &gt; std::accumulate,位于标题<numeric>

Boost.Range中可以找到更多功能性的东西,这是一个非常棒的库。特别是range adaptors给出了真实的功能感,因为他们在其他范围内创建视图。使用C ++ 11,可以通过lambdas轻松创建可能的谓词。

Boost.Optional可能是您的“选项类型”,具体取决于您的具体含义。

只需声明对象const即可实现C ++的不变性。您可以使用by-reference参数传递来避免副本。说实话,这当然不等同于真正的功能不变性,因为功能语言中的不可变容器可以根据需要进行复制,通常只是共享内部表示。毕竟,如果你从不写,那么写拷贝很棒。

在你的管理指针上,我不知道你的意思。在C ++中,通常根本不需要指针或动态分配的对象。只需在“堆栈”中创建它们:Foo obj;

如果您的意思是共享所有权,那就是std::shared_ptr。如果将这样的指针存储在容器中,甚至还有一个很好的范围适配器:

#include <boost/range/adaptor/indirected.hpp>
#include <boost/range/algorithm/generate.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <vector>
#include <memory>
#include <algorithm>
#include <iterator>
#include <iostream>

int main(){
  std::vector<std::shared_ptr<int>> v(5);
  int i = 0;
  boost::generate(v, [&i]{ return std::make_shared<int>(i++); });
  boost::copy(v | boost::adaptors::indirected,
      std::ostream_iterator<int>(std::cout));
}

您的具体示例

  

my_list.map(f).filter(p).head_opt.get_or_else("not found")

可能是这样实现的(注意std::vector是C ++中的默认容器):

// Warning, C++11 only!
// Boost.Range doesn't like lambdas without this:
#define BOOST_RESULT_OF_USE_DECLTYPE

#include <vector>
#include <string>
#include <iterator>
#include <iostream>
#include <boost/optional.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/generate.hpp> // only needed for filling the vector
#include <boost/range/algorithm/copy.hpp> // only needed for printing

// we need a little helper for the optional stuff
struct head_opt_gen{} head_opt; // just a tag type

template<class Range>
auto operator|(Range const& r, head_opt_gen)
  -> boost::optional<decltype(r.front())>
{
  if(r.empty())
    return boost::none;
  return r.front();
}

int main(){
  using namespace boost::adaptors;
  std::vector<int> v(5);
  int i = 0;
  boost::generate(v, [&]()->int{ ++i; return i*i; });
  // first, without the optional stuff
  boost::copy(v | transformed([](int x){ return std::to_string(x); })
                | filtered([](std::string const& s){ return s.size() > 1; }),
      std::ostream_iterator<std::string>(std::cout, "\n"));
  std::cout << "=====================\n";
  // now with
  std::cout << boost::get_optional_value_or(
      v | transformed([](int x){ return std::to_string(x); })
        | filtered([](std::string const& s){ return s.size() > 2; }) // note: > 2
        | head_opt, "none");
}

使用Clang 3.1 Trunk编译,这会产生以下输出:

16
25
=====================
none

答案 1 :(得分:2)

我认为没有任何库明确地使用不可变数据结构。虽然没有人阻止你在某些情况下不改变数据结构。

但你可以从Boost.Range构建一些你想要的东西。它具有强大的基于范围的构造,过滤等。不过,你必须自己处理内存管理。


您的问题似乎是,“C ++中是否存在完全实现严格函数式编程结构行为的库?”答案是不。据我所知,没有C ++库的基本目的是明确地直接实现严格的函数式编程结构。 C ++最终不是一种函数式语言。

各种功能构建有很多近似值。但是没有一个库完全按照严格的函数式编程规则来实现它们。

答案 2 :(得分:1)

FC++似乎是一个较旧的库(2001年代,last modified in 2007 on SourceForge),在C ++中提供了一些函数式编程功能。

嗯,FC++ was submitted as a potential Boost library in 2003

StackOverflow上的其他地方,the primary original developer of FC++ indicated that modern C++ and Boost have superceded some of FC++'s use cases, but that others are still not available in a modern C++ library?

似乎有人甚至写了一篇README for a github project来描述我所要求的内容,但似乎没有进一步了解该项目。

希望这有助于某人...