Существует ли библиотека C ++, аналогичная / эквивалентная функциональной Java? - PullRequest
7 голосов
/ 25 февраля 2012

Существуют ли библиотеки C ++ с открытым исходным кодом, которые аналогичны или эквивалентны превосходной Функциональной библиотеке Java ?

К конкретным функциям относятся:

  • map, fold/ уменьшить, отфильтровать и т. д. на итерациях и т. п.
  • тип опции
  • реализации неизменяемой структуры данных

(из любопытства,отошел от C ++ на несколько лет)

Да, Традиционно считалось, что некоторые из этих функций требуют сборки мусора.Но с современными функциями и библиотеками C ++ кто-нибудь начал передавать управляемые указатели через функциональные преобразования или что-то в этом роде?

ОБНОВЛЕНИЕ Чтобы было ясно, мне интересно, есть что-то похожее на функциональную 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")

Это идиома, которую предлагает функциональная Java, и поверьте мне, к ней действительно легко привыкнуть ...

Ответы [ 3 ]

12 голосов
/ 25 февраля 2012

Как сказал @jalf, карта и фолд уже в стандарте, скрыты за разными именами:

  • карта -> std::transform, находится в заголовке <algorithm>
  • fold -> std::accumulate, найдено в заголовке <numeric>

Многие другие функциональные возможности можно найти в Boost.Range , который является довольно классной библиотекой. В частности, адаптеры дают реальное функциональное ощущение, поскольку они создают просмотров в других диапазонах. В C ++ 11 возможные предикаты также легко создаются на лету через лямбды.

Boost.Optional может быть вашим «типом параметра», в зависимости от того, что именно вы имеете в виду.

Неизменяемость в C ++ может быть достигнута простым объявлением вашего объекта const. Вы можете избежать копирования, используя передачу аргументов по ссылке. По правде говоря, это, конечно, не является реальным эквивалентом истинной функциональной неизменности, поскольку неизменяемые контейнеры на функциональных языках могут быть скопированы по вашему желанию и, как правило, просто разделяют внутреннее представление. В конце концов, копирование при записи - это здорово, если ты никогда не пишешь.

На ваших управляемых указателях я понятия не имею, что вы подразумеваете под ними. В 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
2 голосов
/ 25 февраля 2012

Я не думаю, что есть какие-либо библиотеки, которые явно содержат неизменяемые структуры данных.Хотя никто не мешает вам просто не изменять структуры данных вне определенных контекстов.

Но вы можете создать то, что вы хотите, из Boost.Range .Он имеет мощные конструкции на основе диапазона, фильтрацию и так далее.Вам, однако, придется иметь дело с управлением памятью самостоятельно.


Похоже, ваш вопрос звучит так: «Есть ли в C ++ библиотека, которая точно реализует поведение конструкций строгого функционального программирования?»Ответ - нет.Насколько мне известно, не существует библиотеки C ++, которая имеет своей основной целью явную и прямую реализацию строгих конструкций функционального программирования.C ++ в конечном счете не является функциональным языком.

Существует множество приближений различных функциональных конструкций.Но нет библиотеки, которая реализует их точно по правилам строгого функционального программирования.

1 голос
/ 27 февраля 2012

FC ++ представляется более старой библиотекой (эпоха 2001 года, , последний раз измененной в 2007 году на SourceForge ), предлагающей некоторые функциональные возможности программирования на C ++.

Хммм, FC ++ был представлен в качестве потенциальной библиотеки Boost в 2003 году ?

В другом месте StackOverflow основной первоначальный разработчик FC ++ указал, что современные C ++ и Boost заменили некоторые варианты использования FC ++,но что другие по-прежнему недоступны в современной библиотеке C ++?

Также кажется, что кто-то дошел до написания README для проекта github по сути, это именно то, о чем я просил, но, похоже, не продвинулся дальше с проектом.

Надеюсь, это кому-нибудь поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...