Code Monkey home page Code Monkey logo

dobiasd / functionalplus Goto Github PK

View Code? Open in Web Editor NEW
2.0K 72.0 167.0 2.8 MB

Functional Programming Library for C++. Write concise and readable C++ code.

Home Page: http://www.editgym.com/fplus-api-search/

License: Boost Software License 1.0

C++ 95.73% Shell 0.16% Elm 2.47% JavaScript 0.02% HTML 0.13% CSS 0.26% CMake 0.74% Python 0.49%
range composition stl functional-programming algorithms header-only c-plus-plus c-plus-plus-14 c-plus-plus-17 library

functionalplus's People

Contributors

adela0814 avatar am11 avatar artalus avatar danimtb avatar dflamand avatar dobiasd avatar ferdymercury avatar friendlyanon avatar headupinclouds avatar henryiii avatar jchia avatar kkweon avatar kvaz1r avatar luso58 avatar manwithabike avatar mattpaletta avatar offa avatar paivagustavo avatar pcres91 avatar pfultz2 avatar pthom avatar ruanformigoni avatar scinart avatar seekingmeaning avatar theodelrieu avatar thiagobbt avatar tom91136 avatar unixnme avatar xtofl avatar ztdwu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

functionalplus's Issues

improve documentation

Some functions (like fold_left) do already have a short textual description of what they do.
For some functions this perhaps is not really needed, since the type signature or the example are sufficient.
But some functions could need a description.
enumerate, generate and is_sorted_on are just some that come to my mind right now.

Is anybody interested in browsing trough parts of the code and adding documentation where sensible? I think this would be very helpful, especially for helping users new to the library.

Function adjacent_pairs crashes in MSVC2017 Debug mode

Hi =) adjacent_pairs advances iterator it2 beyond xs.end(), which crashes in debug mode on MSVC 2017 (V 15.2).

#include "fplus/fplus.hpp"
int main() {
	std::vector<int> vec = {1, 2, 4, 5 };
	auto x = fplus::adjacent_pairs(vec);
}

Proposal for a fix: PR

Adding variadic math functions like min, max etc.

I have seen your math functions like min_2, min_3 etc. and I wondered why not use variadic templates to remove duplicated code?

Inspired by http://articles.emptycrate.com/2016/05/14/folds_in_cpp11_ish.html I have made some benchmarks and it came out that variadic versions are faster on -g and on pair with optimizations with your versions.

#include <vector>
#include <functional>
#include <utility>
#include <type_traits>
#include <iostream>
#include <chrono>

template <typename TimeT = std::chrono::milliseconds>
struct measure
{
  template <typename F, typename... Args>
  static typename TimeT::rep execution(F func, Args&&... args)
  {
    auto start = std::chrono::system_clock::now();

    // Now call the function with all the parameters you need.
    func(std::forward<Args>(args)...);

    auto duration = std::chrono::duration_cast<TimeT>(std::chrono::system_clock::now() - start);

    return duration.count();
  }
};

template <typename U, typename... V>
auto min(const U& u, const V&... v)
{
  using rettype = typename std::common_type_t<U, V...>;
  rettype result = static_cast<rettype>(u);
  (void)std::initializer_list<bool>{((v < result) ? (result = static_cast<rettype>(v), false) : false)...};
  return result;
}

// API search type: min_2 : (a, a) -> a
// Minimum of two values.
template <typename X>
const X& min_2(const X& a, const X& b)
{
  return std::min(a, b);
}

// API search type: min_3 : (a, a, a) -> a
// Minimum of three values.
template <typename X>
const X& min_3(const X& a, const X& b, const X& c)
{
  return min_2(min_2(a, b), c);
}

// API search type: min_4 : (a, a, a, a) -> a
// Minimum of four values.
template <typename X>
const X& min_4(const X& a, const X& b, const X& c, const X& d)
{
  return min_2(min_3(a, b, c), d);
}

// API search type: min_5 : (a, a, a, a, a) -> a
// Minimum of five values.
template <typename X>
const X& min_5(const X& a, const X& b, const X& c, const X& d, const X& e)
{
  return min_3(min_3(a, b, c), d, e);
}

int main()
{
  constexpr int COUNT = 50000000;
  std::vector<int> v, v1;
  v.reserve(COUNT);
  v1.reserve(COUNT);

  std::cout << "variadic version: " << '\n';
  std::cout << measure<std::chrono::milliseconds>::execution([&v]()
                                                             {
                                                               for (int i = -COUNT; i < COUNT; ++i)
                                                                 v.emplace_back(min(1, -14, 3, -1, i));

                                                             }) << "ms\n";

  std::cout << "functional plus version: " << '\n';
  std::cout << measure<std::chrono::milliseconds>::execution([&v1]()
                                                             {
                                                               for (int i = -COUNT; i < COUNT; ++i)
                                                                 v1.emplace_back(min_5(1, -14, 3, -1, i));

                                                             }) << "ms\n";
}

It both depends on data and optimizations but I have received the following results (not the measure of all times but hey... :) ):

g++ -g -Wall -Wpedantic -Wextra --std=c++14 main.cpp && ./a.out                                                                                                       
variadic version: 
2240ms
functional plus version: 
4335ms

g++ -O1 -Wall -Wpedantic -Wextra --std=c++14 main.cpp && ./a.out
variadic version: 
333ms
functional plus version: 
307ms

g++ -O2 -Wall -Wpedantic -Wextra --std=c++14 main.cpp && ./a.out
variadic version: 
326ms
functional plus version: 
347ms

g++ -O3 -Wall -Wpedantic -Wextra --std=c++14 main.cpp && ./a.out
311ms
functional plus version: 
321ms

The variadic version is only worse on O1 no idea why...

If anyone is happy with this type of approach I will be more than happy to submit a pull request for some of the functions in numeric which can be easily handled with variadic templates/initializer_list.

[feature request] Better Description & Expose the API search link, "Foogle"

Overview

The Awesome repo needs an awesome description.
So, I have two feature requests:

  1. The current description is too implicative.
  2. Add the Foogle to the description.

After all, it's just a suggestion, so feel free to close it if you think it's not necessary.

1. Too implicative description

By Description, I mean
image

Why?

  • Sure it does help to write in concise and readable C++ code, but it does not truly show what FunctionlPlus is trying to offer. Functional Programming Library for C++
  • When I search "Functional Programming C++," it doesn't show the FunctionalPlus.
    In order to search FunctionalPlus, you have to search "Concise C++ Code".
    image

Possible suggestion

  • Change to Functional Programming Library for C++ or something similar

2. Expose Foogle

By Foogle I mean the API search website http://www.editgym.com/fplus-api-search/
It is truly awesome and super helpful, but it's currently hidden deeply in the README.

Why?

In order to go to the Foogle from this GitHub,

you have to go through 3 steps.

  1. Scroll down until "Finding the functions you need" in the toc
  2. Click "Finding the functions you need"
  3. Click "FunctionalPlus API search website."

Possible suggestions

  • if you provide the link in the description, it's one click to the Foogle.
    image

  • If you don't like it's in the description, I still think it should be located somewhere in the top of README.md, so it's easily accessible.

transform_pair not working with std::function

The following code does not compile any more. I guess it has something to do with PR #87.

const std::function<int(int)> double_int = [](int x) -> int
{
    return 2 * x;
};
typedef std::pair<int, int> IntPair;
fplus::transform_pair(double_int, double_int, IntPair({2,3}));

@theodelrieu, could you please have a look at it?

std

you use many symbols like "std ::" , adding one line that using namespace std will be ok!

Use doxygen

The API-search is neat, but not very useful, because a new user is in a situation "i don't know what I'm looking for". Instead, the user must have a facility to explore the library. I'd recommend annotating public API with doxy-comments and generate documentation from that.

fplus::map_union fails to compile for std::unordered_map

Example code

#include "fplus/fplus.hpp"
#include <unordered_map>

int main(void) {
   std::unordered_map<int, int> foo = fplus::map_union(std::unordered_map<int, int>(), std::unordered_map<int, int>());
   return 0;
}

Observed behavior

Compile error:

error: could not convert โ€˜fplus::map_union_with(F, const MapIn&, const MapIn&) [with F = fplus::map_union(const MapType&, const MapType&) [with MapType = std::unordered_map<int, int>]::<lambda(const Value&, const Value&)>; MapIn = std::unordered_map<int, int>]((* & dict1), (* & dict2))โ€™ from โ€˜std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >โ€™ to โ€˜std::unordered_map<int, int>โ€™
     return map_union_with(get_first, dict1, dict2);

Expected behavior

Code compiles.

Cause?

I'm not sure why this happens, but it seems to have to do with the SameMapTypeNewTypes template

template<class Cont, class NewKey, class NewVal> struct SameMapTypeNewTypes : public std::false_type {};
as used in
using MapOut = typename internal::SameMapTypeNewTypes<MapIn, Key, OutVal>::type;
.

System

I'm using Arch Linux with GCC 8.1.0 and fplus 0.2.1 (the latest release from conan).

I'm happy to help debug further! If I figure out what causes this, I'll submit a PR, but I'm not sure what it is yet...

[question] Generated files when building

Hi,

I have seen that in order to use this library you have to generate some files with CMake.
In my case they were two files: curry_instances.autogenerated_defines and fwd_instances.autogenerated_defines.

I would like to know if those generated files may be different depending on the operating system, compiler used or not.

Thank you

drop_if_with_idx() โ€“ what's wrong here?

Here's an example where keep_if_with_idx() is Ok, but drop_if_with_idx() fails to compile:

Predicate

static bool accept_with_index(size_t index, int value)
{
    return ( index % 2 == 0 ) && ( value >= 10 );
}

keep_if_with_idx() โ€“ Works

const std::vector<int> v = { 1, 20, 30, 4, 50, 60, 7 };
auto result = fplus::keep_if_with_idx(accept_with_index, v);
// Result: { 30, 50 }

drop_if_with_idx() โ€“ Fails to compile

const std::vector<int> v = { 1, 20, 30, 4, 50, 60, 7 };
auto result = fplus::drop_if_with_idx(accept_with_index, v);
// Expected Result: { 1, 20, 4, 60, 7 }  --- Compilation fails

Compilation fails due a failed static assertions ("Wrong arity").


Is there a mistake in the example / usage of drop_if_with_idx()?

unknown type name 'uint'; did you mean 'int'? using clang++

Problem

Thanks for the awesome library first of all.
During compilation, I get the following error messages.

Please let me know if you need more information.

Thank you.

First Error

/usr/local/include/fplus/composition.hpp:385:29: error: unknown type name 'uint'; did you mean 'int'?

Second Error

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:668:78: error: implicit instantiation of
      undefined template 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >'
    _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(const typename _Container::value_type& __value_)

Third Error (same as second)

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:671:72: error: implicit instantiation of
      undefined template 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >'
    _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(typename _Container::value_type&& __value_)

What I did

  • Using cmake
git clone https://github.com/Dobiasd/FunctionalPlus
cd FunctionalPlus
mkdir build
cd build
cmake ..
sudo make install
  • Save the tutorial code as main.cpp
#include <fplus/fplus.hpp>
#include <iostream>

int main() {
  std::list<std::string> things = {"same old", "same old"};
  if (fplus::all_the_same(things))
    std::cout << "All things being equal." << std::endl;
}
  • Compile
clang++ -std=c++14 main.cpp
  • Results:
In file included from main.cpp:1:
In file included from /usr/local/include/fplus/fplus.hpp:10:
/usr/local/include/fplus/composition.hpp:385:29: error: unknown type name 'uint'; did you mean 'int'?
        return [f, storage](uint x)
                            ^
In file included from main.cpp:1:
In file included from /usr/local/include/fplus/fplus.hpp:9:
In file included from /usr/local/include/fplus/compare.hpp:9:
In file included from /usr/local/include/fplus/function_traits.hpp:25:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:477:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:606:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:668:78: error: implicit instantiation of undefined template 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >'
    _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(const typename _Container::value_type& __value_)
                                                                             ^
/usr/local/include/fplus/container_common.hpp:111:16: note: in instantiation of template class 'std::__1::back_insert_iterator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >' requested here
        return std::back_inserter(ys);
               ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd:193:33: note: template is declared here
    class _LIBCPP_TYPE_VIS_ONLY basic_string;
                                ^
In file included from main.cpp:1:
In file included from /usr/local/include/fplus/fplus.hpp:9:
In file included from /usr/local/include/fplus/compare.hpp:9:
In file included from /usr/local/include/fplus/function_traits.hpp:25:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:477:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:606:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iterator:671:72: error: implicit instantiation of undefined template 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >'
    _LIBCPP_INLINE_VISIBILITY back_insert_iterator& operator=(typename _Container::value_type&& __value_)
                                                                       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/iosfwd:193:33: note: template is declared here
    class _LIBCPP_TYPE_VIS_ONLY basic_string;
                                ^
3 errors generated.

My setup

  • OSX
  • clang(++)
clang++ --version
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

using std::array

The following code does not compile.

#include <fplus/fplus.hpp>
int main()
{
    std::array<int, 3> xs = {0,1,2};
    fplus::transform(fplus::square<int>, xs);
}

fplus::transform (and some other functions) could deduce the length of the returned sequence at compile time and thus support std::array in theory.

I'm thinking about adding this functionality, but I'm still in the process of gathering ideas around this topic. Any thoughts? :)

The function name 'unique' is a little misleading

I'm glad to just find this great library! After some exploration, I found that the function name unique is a little misleading. Here unique([1,2,2,3,2]) == [1,2,3,2], though I would expect unique([1,2,2,3,2]) == [1,2,3] as the behavior of numpy.unique in python.

Despite this name is followed from std::unique, which remove consecutive duplicates in range, I personally think using a slight different name (e.g. unique_consecutime) here would be beneficial for avoiding misuse. However it's just personal thought. Please feel free to take it or leave it :)

Clean-up: static_asserts

There are a lot of duplicate function_traits_asserts specialization.

We need to group them.

Also, since C++14 constexpr functions can return void, which would remove the cast to void on each call to detail::trigger_static_asserts

Clean-up: merge namespaces detail && internal

Renaming detail to internal is the first step. There are a few internal methods that are superseded by those in detail.

There's also some static_assert that do not use the detail::trigger_static_assert facility.

errors when using conan

i wanted to try frugally-deep through the conan package manager,

however i'm not able to compile, getting a lot of errors like:

~.conan/data/functionalplus/v0.2-p1/dobiasd/stable/package/5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9/include/fplus/internal/meta.hpp:28:41: error: no template named 'remove_reference_t' in namespace 'std'; did you mean 'remove_reference'?
using uncvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
                                   ~~~~~^~~~~~~~~~~~~~~~~~
                                        remove_reference

not sure if this is a bug in FunctionalPlus or i'm doing something wrong.

conanfile.txt:

[requires]
frugally-deep/v0.3.3-p0@dobiasd/stable


[generators]
cmake

could not deduce template argument for 'ContainerOut'

Hi,

I have just started playing with FunctionalPlus using Microsoft Visual Studio 2015 and have this stupid building error that I've been fighting with all day:

1> fplus_tutorial.cpp 1>.......\include\fplus\container_common.hpp(1166): error C2783: 'ContainerOut fplus::transform(F,ContainerIn &&)': could not deduce template argument for 'ContainerOut'

is that something known? I've been googling a lot and checking everything on my side, but it just look like that code can't be really handled by VS15.

Many thanks in advance for help.

BR,
Konrad

constructor_as_function and std::initializer_list

Hi, I think there is a problem with the implementation of constructor_as_function.

return T{args...};

IIRC, make_unique uses parenthesis instead of curly braces, I believe we should do the same.

Here is the current behavior:

struct Test {
  Test(int, int){} // 1
  Test(std::initializer_list<int>){} // 2
};

fplus::constructor_as_function<Test>(4, 2); // will call constructor 2

Clean-up: use invoke everywhere

In order to support every Callable object, we should use invoke instead of:

// will not work with pointers/references to member functions/data members
return f(x, y);

error: 'fwd' has not been declared (gcc version 4.9.2)

When I compile followinf code from usage-examples:

#include <fplus/fplus.hpp>
#include <iostream>

int main()
{
using namespace fplus;
const auto result_fplus = fwd::apply(
    numbers(0, 15000000)
    , fwd::transform(times_3)
    , fwd::drop_if(is_odd)
    , fwd::transform(as_string_length)
    , fwd::sum());
}

get error:

error: 'fwd' has not been declared
const auto result_fplus = fwd::apply(
...

is it possible rewrite it without updated of the compiler?

Compile error when using transparent function objects

Hello, awesome lib! I was playing a bit with it and I have the following example code that compiles and runs as expected:

#include <iostream>
#include <vector>
#include <string>

#include <fplus/fplus.hpp>

using namespace std::string_literals;

int main()
{
  auto const l1 = {"Hello"s, "World"s};
  auto const l2 = {","s, "!"s};
  auto const v = fplus::zip_with(std::plus<std::string>{}, l1, l2);
  std::cout << fplus::show_cont_with(" ", v) << std::endl;
}

However, when I use std::plus<>{}, I get a compiler error (VS2017 on Win10 x64):

include\fplus/function_traits.hpp(79): error C3556: 'std::plus::operator ()': incorrect argument to 'decltype'
include\fplus/pairs.hpp(42): note: see reference to class template instantiation 'utils::function_traits' being compiled
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\chrono(227): note: see reference to class template instantiation 'std::chrono::duration<__int64,std::nano>' being compiled
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\chrono(1002): note: see reference to class template instantiation 'std::chrono::time_pointstd::chrono::steady_clock,std::chrono::steady_clock::duration' being compiled
include\fplus/function_traits.hpp(80): error C2955: 'utils::function_traits': use of class template requires template argument list
include\fplus/function_traits.hpp(79): note: see declaration of 'utils::function_traits'
include\fplus/pairs.hpp(42): error C2039: 'arity': is not a member of 'utils::function_traits'
include\fplus/pairs.hpp(42): note: see declaration of 'utils::function_traits'
include\fplus/pairs.hpp(42): error C2065: 'arity': undeclared identifier
include\fplus/pairs.hpp(45): error C2903: 'arg': symbol is neither a class template nor a function template
include\fplus/pairs.hpp(45): error C2039: 'type': is not a member of 'utils::function_traits'
include\fplus/pairs.hpp(42): note: see declaration of 'utils::function_traits'
include\fplus/pairs.hpp(45): warning C4091: 'typedef ': ignored on left of 'int' when no variable is declared
include\fplus/pairs.hpp(45): error C2144: syntax error: 'unknown-type' should be preceded by ';'
include\fplus/pairs.hpp(46): error C2903: 'arg': symbol is neither a class template nor a function template
include\fplus/pairs.hpp(46): error C2039: 'type': is not a member of 'utils::function_traits'
include\fplus/pairs.hpp(42): note: see declaration of 'utils::function_traits'
include\fplus/pairs.hpp(46): warning C4091: 'typedef ': ignored on left of 'int' when no variable is declared
include\fplus/pairs.hpp(46): error C2144: syntax error: 'unknown-type' should be preceded by ';'
include\fplus/pairs.hpp(49): error C2923: 'std::is_convertible': 'FIn0' is not a valid template type argument for parameter '_To'
include\fplus/pairs.hpp(45): note: see declaration of 'FIn0'
include\fplus/pairs.hpp(49): error C2955: 'std::is_convertible': use of class template requires template argument list
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\type_traits(416): note: see declaration of 'std::is_convertible'
include\fplus/pairs.hpp(50): error C2057: expected constant expression
include\fplus/pairs.hpp(51): error C2923: 'std::is_convertible': 'FIn1' is not a valid template type argument for parameter '_To'
include\fplus/pairs.hpp(46): note: see declaration of 'FIn1'
include\fplus/pairs.hpp(51): error C2955: 'std::is_convertible': use of class template requires template argument list
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\type_traits(416): note: see declaration of 'std::is_convertible'
include\fplus/pairs.hpp(52): error C2057: expected constant expression

I never really used transparent function objects, so it might very well be a silly mistake.

Infinite ranges - generators

Very nice library!
I find some similarities with ranges v3 from Eric Niebler.

Strong points toward yours are being more portable and faster to compile.

Anyway i'd like some more features that are missing, such as infinite ranges and generators.
For example i would really like to do:

std::vector<std::string> vec = {"first", "second", "third"};
for(auto & el : fplus::zip(vec, fplus::generate_range(1))
    std::cout << el.first << " " << el. second << '\n';

// outputs:
// first 1
// second 2
// third 3

scan_right_1 API doc

Thank you for creating FunctionalPlus!
I was interested in it, and reading code and made memo/summary for my use, then found small error in API doc for scan_right_1
Probably, result [1,3,6] is remain of copy&paste from scan_left_1, isn't it?
I get == [6,5,3] as expected.

quote container_common.hpp line:522

// API search type: scan_right_1 : (((a, a) -> a), [a]) -> [a]
// scan_right_1((+), [1, 2, 3]) == [1, 3, 6]
// Takes the last two items of the list and applies the function,
// then it takes the third item from the end and the result, and so on.
// It returns the list of inntermediate and final results.
template <typename F, typename ContainerIn,
typename Acc = typename ContainerIn::value_type,
typename ContainerOut = typename same_cont_new_t<ContainerIn, Acc>::type>
ContainerOut scan_right_1(F f, const ContainerIn& xs)
{
return reverse(scan_left_1(flip(f), reverse(xs)));

}

Leveraging C++ 14 features for forward function application (unix pipe style). What is your opinion on this?

Let's say we have the following three functions

const auto times_3 = [](int i){return 3 * i;};
const auto is_odd = [](int i){return i % 2 == 0;};
const auto as_string_length = [](int i){return std::to_string(i).size();};

and want to transform/filter a sequence of numbers with them and sum up the result.

Up to now, we would have to write the following:

const auto result_old_style =
    sum(
    transform(as_string_length,
    drop_if(is_odd,
    transform(times_3,
    numbers(0, 15000000)))));

I do not like the fact that we have to read backwards to perceive the flow of data. I think something in the style of unix pipes would be nicer.

With some additional code in the library we could do the following thing:

const auto result_new_style = fwd::apply(
    numbers(0, 15000000)
    , fwd::transform(times_3)
    , fwd::drop_if(is_odd)
    , fwd::transform(as_string_length)
    , fwd::sum());

Furthermore it would solve the problem of the almost unusable-ugly function composition, going from this:

const auto function_chain_old_style = compose(
    bind_1st_of_2(transform<decltype(times_3), std::vector<int>>, times_3),
    bind_1st_of_2(drop_if<decltype(is_odd), std::vector<int>>, is_odd),
    bind_1st_of_2(transform<decltype(as_string_length), std::vector<int>>, as_string_length),
    sum<std::vector<std::size_t>>);

to that:

const auto function_chain_new_style = fwd::compose(
    fwd::transform(times_3),
    fwd::drop_if(is_odd),
    fwd::transform(as_string_length),
    fwd::sum());

Transforming over the inner containers in nested ones

typedef std::vector<int> ints;
std::vector<ints> nested_ints;

would thus also become simpler, going from:

const auto nested_transformed_old_style = transform(
    bind_1st_of_2(transform<decltype(times_3), ints>, times_3),
    nested_ints);

to

const auto nested_transformed_new_style = fwd::apply(
    nested_ints
    , fwd::transform(fwd::transform(times_3)));

It would increase the compiler requirements from C++11 to C++14. But this functionality could be provided in a separate header, so one could still use the old style when only C++11 is available.
Here is the full code of the example above. (The code up to line 104 would live in a file perhaps called fwd.hpp.)

What do you think about this idea?

std::initializer_list

It seems that at least some functions don't work with initializer_list. Is it possible to make make them work? For example, this doesn't compile:

void foo(initializer_list<int> const& x) {
    fplus::transform([](int i){ return i + 1;}, x);
}

Clean-up: remove result_of occurences

result_of is deprecated in C++17, and has a lot of caveats.

We should use invoke_result_t instead. Note that invoke_result_t returns a T&& (as std::declval).

It is important to be careful when storing it into a template type:

using Result = detail::invoke_result_t<F>;
// std::vector<T&&> will fail to compile
// using ContainerOut = std::vector<Result>;
using ContainerOut = std::vector<std::decay_t<Result>>;

Taking advantage of move-semantics.

e.g. let's look at keep_if

template <typename Pred, typename Container>
Container keep_if(Pred pred, const Container& xs)
{
    internal::check_unary_predicate_for_container<Pred, Container>();
    Container result;
    auto it = internal::get_back_inserter<Container>(result);
    std::copy_if(std::begin(xs), std::end(xs), it, pred);
    return result;
}

It looks to me it would be better implemented as

template <typename Pred, typename Container>
Container keep_if(Pred pred, Container xs)
{
    // erase-remove elements from xs, per predicate
    return xs;
}

This way if the container is passed as rvalue, as would most likely be the case, then we have no copy-overhead: xs is passed by-move, edited in-place, and returned by-move.

This is not just applicable to keep_if, but the family of functions where input and output types are the same, and the input is likely to be passed as rvalue, and the type is potentially heavy to copy.

Room for performance improvement in `split_by`

The performance of split_by can be improved by using a more efficient tokenizing algorithm as written here (not by me) http://tcbrindle.github.io/posts/a-quicker-study-on-tokenising. I've included an inlined version of the algorithm in the test program below. Here are the execution times of splitting a short string 5,000,000 times, compiled with -O3 on clang 3.7 on x86_64 Linux 4.3:

Time taken: 19.8554 (fplus::split_words)
Time taken: 2.02921 (improved version)
#include <algorithm>
#include <chrono>
#include <iostream>
#include <vector>
#include "fplus.h"

// Slightly modified code based on http://tcbrindle.github.io/posts/a-quicker-study-on-tokenising/
template <typename Str, typename Container = std::vector<std::string>>
Container tokenize(const Str &str, const char delim = ' ') {
    Container result;
    auto inserter = std::inserter(result, std::begin(result));

    auto token_start = std::begin(str);
    while (token_start != std::end(str) && *token_start) {
        const auto token_end = std::find(token_start, std::end(str), delim);
        if (token_start != token_end) {
            *inserter = { token_start, token_end };
        }
        if (token_end == std::end(str)) break;
        token_start = std::next(token_end);
    }
    return result;
}


int main() {
    using namespace std::chrono;

    auto words = std::string{ "a bb ccc dddd eeeee ffffff ggggggg hhhhhhhhh" };

    const auto start_time = high_resolution_clock::now();
    for (auto _ = 0; _ < 5000000; _++) {
        // auto tokens = fplus::split_words(words);
        auto tokens = tokenize(words);
    }
    const auto elapsed = high_resolution_clock::now() - start_time;
    std::cout << "Time taken: " << duration_cast<duration<double>>(elapsed).count() << std::endl;
}

util::function_traits fails with generic lambda on MSVC

This works out of the box - great!

auto cpp11_odd = [](int i) { return i % 2 != 0; };
fplus::keep_if(cpp11_odd,
    generate_range<std::vector<int>>(10, 1000));

This fails with C3556 on VS2015:

auto cpp14_odd = [](auto i) { return i % 2 != 0; };
fplus::keep_if(cpp14_odd,
    generate_range<std::vector<int>>(10, 1000));

Output-Build.txt

If that would work out of the box... great!

Adding Unit Tests?

What about adding unit tests to the project?

I have written some example tests, see here: https://github.com/offa/FunctionalPlus/tree/ut_gtest (test directory)

The tests are off per default at the moment โ€“ so no dependencies are needed. Only Building / running the unit tests requires gtest. To do so:

cd build
cmake -DUNITTEST=ON ..
make unittest

You can check the CI log's for the branch to see how it works.

Btw. I stumbled over #20 by writing an UT for it ๐Ÿ‘

enable clang in travis CI

Currently our travis ci configuration uses 4 different g++ versions for the tests. I think it would be cool if it could use at least one version of clang additionally.
@offa: Is this something you could have a look at?

Is it compilable for avr?

Have you tried to compile this code for Arduino like hardware?
I'm failing on my first attempt . Looks like avr stl library is missing something that you need.
I'm a scala developer, and every time I write for(int i=0..... something small is dying in me.

using libc++ on travis

To consolidate the problem I open this new issue.

Situation: We would like to use recent versions of libc++ on Travis (Ubuntu Trusty).
The default version provided with sudo apt install libc++-dev is svn199600 (_LIBCPP_VERSION is defined as 1101).

My attempts to learn about how to do it on SO (1, 2) were not successful yet.

'recursive' #includes should not require includes/fplus on the include path

E.g. composition.h contains an include

#include "function_traits.h"

Which means that, when included from anywhere, the client project needs both fplus_installation/includes and fplus_installation/includes/fplus on it's include path.

This makes adoption harder, and makes collisions with other libraries more probable.

Public headers should assume as little as possible from client code: they should probably include their neighbour headers as if specified by client code:

#include "fplus/function_traits.h"

Clean-up: default template arguments

There's a lot of defaulted template arguments in the library, they are primarily used to deduce function return types.

The problem is that one can accidentally replace them, and they make the search API less clear.

Most can be removed thanks to C++14's return type deduction.
However, it seems that a few are designed to be replaced? If so, making a list would greatly help to remove the unneeded ones.

Changing the header files does not trigger a rebuild of the unittests

Since #112 I encounter a new effect when changing the library and running the unittests.

My usual workflow looks like this:

initially:

rm -r build
mkdir build
cd build
cmake -DUNITTEST=ON ..
make unittest

later:

# change something in one of the header files
make unittest

With the old versions of CMakeLists.txt and test/CMakeLists.txt it still works, but with the new ones the second make unittest does not rebuild the tests. It just ignores the changes in the header files. I have to run sudo make install to rebuild the tests.

@offa and @theodelrieu Is this intended and my workflow is just strange? Or do you think it would be possible and helpful to change the cmake configuration to support this again?

fplus::transform: taking advantage of move-semantics

With closing issue #73 we introduced the possibility of container re-usage for many functions like keep_if, get_segment and sort.

In the general case the output container of fplus::transform does not have the same type as the input container, but in case the given function is of type a -> a this can happen. For these cases I would like the function to reuse the input container if it is an r-value.

But currently I am banging my head against the wall trying to implement it, i.e. the unit tests won't compile. Would anybody of you guys like to help me out here?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.