Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature functional tooling start #74

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

Sqeaky
Copy link
Member

@Sqeaky Sqeaky commented Aug 14, 2020

This PR isn't complete yet, but when done it will include a basic set of tools for functional programming.

@Sqeaky Sqeaky requested a review from MakoEnergy August 14, 2020 05:01
@Sqeaky Sqeaky added this to the 1.0 milestone Aug 14, 2020
@Sqeaky
Copy link
Member Author

Sqeaky commented Aug 14, 2020

I have three different mechanisms for implementing a small set of functional tools. I want to get input on these and discuss what the best way forward is.

I think the 3 parameter functions has the least promise. These were the simplest to implement because they just use normal template parameter deduction, but specify the type as a parameter also the value of that parameter to matter. for now it just appends to the output set of each function. This isn't idiomatic but could be useful if we go this way.

The 2 parameter functions like the current Convert and Reject work, and are simple. They can be combined in interesting ways with the currying functions to achieve just about anything. I think nesting a bunch of function can lead to gross syntax and I think that is likely with this.

The 2 parameter select function has a bunch of gross machinery behind it. It should be able to fully interoperate with the two parameter functions however we want, but it can also curry itself. If given a predicate and no data it will return a function that accepts data and performs the previously setup selection. This has the drawback of being a bit complex, but I ability to curry without needing to explicitly call a seperate function makes it easier to construct a cleaner syntax for chaining transformations. I am experimenting with this in the Pipe class, which mostly noise right now.

@Sqeaky
Copy link
Member Author

Sqeaky commented Aug 14, 2020

I know this is really rough, most of it can be ignored. The main work and experiments are in "FunctionalTools.h" and "FunctionalToolsTests.h"

Copy link
Member

@MakoEnergy MakoEnergy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished my initial pass. Aside from the obvious stuff of needing to document and wondering where you are going with the piping...it looks good thus far.

Copy link
Member

@MakoEnergy MakoEnergy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished second pass of the current state of the code.

Comment on lines 124 to 127
decltype(auto) Name(const CVIncomingContainerType& IncomingContainer) \
{ \
return StructName{}(std::forward<const CVIncomingContainerType&>(IncomingContainer)); \
} \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You aren't using a universal reference for the parameter here, so I don't think you need the forward.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I need to spend time cleaning this kind of noise up. This is from repeated tests/refactors and never cleaning it up.

Comment on lines 85 to 90
decltype(auto) Name(const CVIncomingContainerType& IncomingContainer, PredicateType Predicate) \
{ \
return StructName<>{} \
(std::forward<const CVIncomingContainerType&>(IncomingContainer), \
std::forward<PredicateType>(Predicate)); \
} \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like below, no need for forward when not using universal reference.

START_FUNCTOR_END_CONTAINER_TO_DATA_AUTOCURRY(MinStruct)
template<typename CVIncomingContainerType, typename PredicateType>
[[nodiscard]] constexpr
decltype(auto) operator() (CVIncomingContainerType&& IncomingContainer, PredicateType Predicate) const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure which is intentional, but it's odd that you are passing predicate by const reference in the function above this one, but by value in this one. AND you are forwarding this one (which again, no universal reference so no need).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will try to change the predicates to universal references.

using IncomingContainerType = std::decay_t<CVIncomingContainerType>;
using namespace ContainerDetect;
static_assert(IsRange<IncomingContainerType>(),
"Mezzanine::MinMax only determines the Min from containers or ranges.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this message should say "Mezzanine::Min" instead of "MinMax".

Comment on lines 222 to 228
auto Results = std::minmax_element(IncomingContainer.cbegin(), IncomingContainer.cend());
return std::pair{*Results.first, *Results.second};
}
else
{
auto Results = std::minmax_element(IncomingContainer.cbegin(), IncomingContainer.cend(), Predicate);
return std::pair{*Results.first, *Results.second};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/nit Is use of std::make_pair appropriate here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Comment on lines 52 to 54
namespace Mezzanine
{
namespace Functional {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/nit I find your lack of consistency....disturbing.


// Convert this when assiging to strongly typed storage.
[[nodiscard]] constexpr
operator auto() const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type is cleanly known. No need for "auto".

if constexpr( HasReserve<ReturnContainerType>())
{ Results.reserve(HowMany); }

for(SizeType Counter{0}; Counter<HowMany; Counter++, Copying++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/nit Some spaces around the operator for visibility would be nice.

if constexpr( HasReserve<ReturnContainerType>())
{ Results.reserve(HowMany); }

for(SizeType Counter{0}; Counter<HowMany; Counter++, Copying++)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/nit Same nit as before.

Comment on lines +817 to +822
if constexpr(HasPushBackValue<ReturnContainerType>())
{ Results.push_back(*Copying); }
else if constexpr(HasInsertValue<ReturnContainerType>())
{ Results.insert(*Copying); }
else if constexpr(HasAddValue<ReturnContainerType>())
{ Results.add(*Copying); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For all of the operations that copy the elements, should we static_assert to verify the element is copy constructable? I also have the slightest bit of concern about situations where a moving variant of these functions may be selected instead of the copy.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are const iterators pointing into a const container, moving shouldn't be possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants