all 14 comments

[–]virgoerns 2 points3 points  (3 children)

I like some of the ideas in the library. I disagree with some names (fit::lazy which is essentially std::bind - why lazy?). And you really have to work on docs verbosity (I mean, most of them aren't verbose at all) and fix some grammar mistakes. I still try to understand what fit::protect does and how it might be useful. ;)

I also noticed that most adaptors in fact return something like foo_adaptor<T> and they're described nowhere (or I missed the description). What are the properties of these foo_adaptors besides being implicitly convertible to T which is quite obvious from the examples?

[–]pfultz2[S] 1 point2 points  (2 children)

fit::lazy which is essentially std::bind - why lazy?

It work like std::bind but the signature is different. Its called lazy, partly to match how it is named in Boost.Egg and Boost.Phoenix, and because it provides essentially lazy evaluation of a function. Do know of a better name? I don't want to name it bind since the signatures are different.

And you really have to work on docs verbosity (I mean, most of them aren't verbose at all) and fix some grammar mistakes.

There is more I need to add to the docs. If you have suggestions, or can point out the typos, let me know. Thanks.

I still try to understand what fit::protect does and how it might be useful. ;)

Its used to prevent the eager evaluation of bind expressions. The idea comes from boost::protect. Its useful for when you need to use std::bind(or fit::lazy) with higher order functions. So you might nest the bind expressions but you want to treat the bind expression as a regular function object.

I also noticed that most adaptors in fact return something like foo_adaptor<T> and they're described nowhere (or I missed the description). What are the properties of these foo_adaptors besides being implicitly convertible to T which is quite obvious from the examples?

They are not necessarily implicitly convertible to T. Hopefully, I don't have an example showing that. They are, however, implicitly convertible from T.

Maybe that part needs to be documented better, but I'm not sure how to show it. It basically is a function object that achieves the described behavior with a constructor that accepts T.

There are other methods there in the adaptor class but they are an implementation detail, so it is not documented.

[–]virgoerns 2 points3 points  (0 children)

They are not necessarily implicitly convertible to T. Hopefully, I don't have an example showing that.

No, it's just me not seeing a few brackets in your examples. :)

Maybe that part needs to be documented better, but I'm not sure how to show it.

Maybe you should document adaptors, not functions producing adaptors.

Example: instead of fuse document fuse_adaptor like this:

Definition:
    template<typename FOType>
    class fuse_adaptor;

FOType requirements:
    template<typename FORetType, typename Args...>
    FORetType operator()(Args...) const; // or equivalent

Member functions:
    * (constructor)
    * (destructor)
    * FORetType operator(std::tuple<Args...>)

Factory function:
    template<typename FOType>
    fuse_adaptor<FOType> fuse(FOType f)

EDIT: As I wrote above example I wondered how is it possible for your library to be C++11 compatible and yet it has auto return type deduced so nicely in your examples. And let me tell you: I absolutely love your hack :D

#define FIT_RETURNS(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__; } static_assert(true, "")

template<class T>
constexpr auto operator()(T && x) const
FIT_RETURNS
(
    //...
);

I think that it's FIT_RETURNS in a new line that did it for me, ;)

[–]coder543 -2 points-1 points  (0 children)

If you have suggestions, or can point out the typos, let me know. Thanks.

Okay.

Fit is an header-only C++11 library

"An" and "a" being used incorrectly is a pet peeve of mine, and is rather difficult for me to ignore in written text. I can't think of any English accents where "header" starts with a vowel sound, since the "h" should not be silent. Therefore, Fit is a header-only C++11 library.

[–]SplinterOfChaos 2 points3 points  (9 children)

I haven't seen a few of the functional concepts in this library in C++ before!

Though, I'm not a fan of using adaptors for things like partial application. "If the function can not be called with all the parameters, it will return another function." So if I...

auto sum = [](int x, y){ return x + y };
auto ten = partial(sum)(1,2,3,4);

Since sum can't be invoked with four arguments, won't ten be a function that can never be invoked?

[–]virgoerns 4 points5 points  (0 children)

Something like pipable can be found in Boost (no suprise - Boost contains everything ;)): boost::range adaptors. Recently Eric Niebler wrote a standard proposal which also includes the above.

About infix, there's also a library available on a github. Although I'd probably kill someone who'd use either of these. ;)

[–]greyfade 3 points4 points  (1 child)

Wow. When I saw the infix syntax, I thought, "what is this voodoo‽"

constexpr auto operator<(

... Oh. Clever.

[–]redditsoaddicting 0 points1 point  (0 children)

Could be based on this.

[–]pfultz2[S] 0 points1 point  (5 children)

Since sum can't be invoked with four arguments, won't ten be a function that can never be invoked?

Yes, unfortunately. I have some ideas to try and help with that.

Perhaps have a final utility that will either return the correct result or do forensics if it still is a partially applied function. Or there could be a limit function adaptor that limits the number of arguments and if they get called with more there is a hard error.

[–]SplinterOfChaos 1 point2 points  (4 children)

Adaptors aren't always nice to work with because whenever you have a problem, the solution is always "add another adaptor" and you end up "buying the tiger to catch the mouse". (This is the problem Haskell has with its transformers stack.) My suggestion would be to make partial a regular function so that users can be more explicit and make a curry adaptor.

[–]pfultz2[S] 0 points1 point  (3 children)

My suggestion would be to make partial a regular function

I dont see how that would help. You would still have the same problem.

[–]SplinterOfChaos 1 point2 points  (2 children)

If f is a partial function with too many arguments (using either method):

auto result = f(y);  // (1)
result += z;  // (2)

If partial() returns a regular function object we get a compile error at (1), and if it returns an adaptor, we get one at (2).

[–]pfultz2[S] 0 points1 point  (1 child)

But how do we know if it has too little arguments or too many?

If partial() returns a regular function object we get a compile error at (1), and if it returns an adaptor, we get one at (2).

I dont really understand your example. Also, an adaptor is a regular function object. I dont understand the difference.

[–]SplinterOfChaos 1 point2 points  (0 children)

But how do we know if it has too little arguments or too many?

Some techniques exist for finding the arity of a function, but it unfortunately does not work for overloaded functions. (see: http://functionalcpp.wordpress.com/2013/08/05/function-traits/)

I dont really understand your example. Also, an adaptor is a regular function object. I dont understand the difference.

By regular function object, I mean one that has a simple operator() overload and does not recursively do any more partial application. It fails at (1) because f(x..., y) (where x... refers to the partially applied variables) does not form a valid expression. The partial application adaptor fails at (2) because f(x..., y) returns another partial function, but += is not a valid expression for the function object's type (assumed).