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] Adds all_of traits for type list and parameter packs. #1214

Merged
merged 2 commits into from
Oct 9, 2019

Conversation

rrahn
Copy link
Contributor

@rrahn rrahn commented Aug 15, 2019

Allows to reduce a type pack or type list by checking a predicate on the type identiry of each type.

@rrahn rrahn requested a review from h-2 August 15, 2019 11:53
@eseiler
Copy link
Member

eseiler commented Aug 15, 2019

Without looking too much into it, it seems similar to std::conjunction but more flexible.

Copy link
Member

@h-2 h-2 left a comment

Choose a reason for hiding this comment

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

I have some general design concerns, maybe also because I have more of the type_list stuff laid out in my head than is written in code already.

In general I had planned:

pack_traits::apply (takes a transformation trait, applies to every element) [in #1215 ]
pack_traits::apply_v (takes a type trait, applies to every element) [naming not clear yet]

Other names for these could be pack_traits::transform. Or one could use that for something else.

What your proposal does is in fact running an arbitrary function on some values, with the exception that those values are previously constructed from types. With the purpose of later passing a lambda that also actually doesn't to anything other than evaluating a type property.
This is switching between type-space and value-space quite often which is not easy to understand and likely also not the best thing for compiler performance (although I am not sure about it).

I see that we might want the ability to run lambdas on a type list, but I would prefer if we can discuss the general design before blowing it up.

Can you do one of the simpler temporary solutions for #863 like defining a concept and immediately expanding on that?

{
return false;
}
//!\endcond
Copy link
Member

Choose a reason for hiding this comment

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

Currently the design is that traits should either SFINAE or fail if instantiating them fails. Adding another possibility of "silently working" make this more complicated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure, what you mean but if I have something that does not SFINAE on an instantiation failure and is still ill-formed it will fail. It's only that you can use in addition SFINAE and do not provide a default case for every trait to test.

include/seqan3/core/type_list/traits.hpp Outdated Show resolved Hide resolved
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from 1053361 to 4678c39 Compare August 15, 2019 13:46
@codecov
Copy link

codecov bot commented Aug 15, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@ebd0790). Click here to learn what that means.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1214   +/-   ##
=========================================
  Coverage          ?   97.59%           
=========================================
  Files             ?      220           
  Lines             ?     8956           
  Branches          ?        0           
=========================================
  Hits              ?     8741           
  Misses            ?      215           
  Partials          ?        0
Impacted Files Coverage Δ
include/seqan3/io/sequence_file/output.hpp 100% <ø> (ø)
include/seqan3/io/sequence_file/input.hpp 100% <ø> (ø)
include/seqan3/core/simd/view_to_simd.hpp 90.47% <ø> (ø)
include/seqan3/io/detail/misc.hpp 100% <100%> (ø)
include/seqan3/core/detail/pack_algorithm.hpp 100% <100%> (ø)
...gnment/configuration/align_config_aligned_ends.hpp 100% <100%> (ø)
include/seqan3/search/configuration/max_error.hpp 100% <100%> (ø)
...ude/seqan3/search/configuration/max_error_rate.hpp 90% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ebd0790...225023f. Read the comment docs.

@rrahn
Copy link
Contributor Author

rrahn commented Aug 15, 2019

In general I had planned:

pack_traits::apply (takes a transformation trait, applies to every element) [in #1215 ]
pack_traits::apply_v (takes a type trait, applies to every element) [naming not clear yet]

Other names for these could be pack_traits::transform. Or one could use that for something else.

Besides that apply means to invoke a function on all arguments and not element wise, we will likely add more algorithms on types because they are useful in many places. At least that is what I had planned.

What your proposal does is in fact running an arbitrary function on some values, with the exception that those values are previously constructed from types. With the purpose of later passing a lambda that also actually doesn't to anything other than evaluating a type property.
This is switching between type-space and value-space quite often which is not easy to understand and likely also not the best thing for compiler performance (although I am not sure about it).

Well, I can't be sure either but it looks like that the compiler will not not have problems optimizing this. Anyway, if performance is your biggest concern we need to use a third library from people that have spent a good time optimising this.

In general, this is so much easier than the pure type based approach and closer to modern c++. You don't need to pollute the namespace with helper structs as you can directly call it in the compile time expression with a lambda. Once we have template names it will become even more easier with lambdas because you don't need the decltype anymore. It is a generic solution that can be used in type and value land.

I see that we might want the ability to run lambdas on a type list, but I would prefer if we can discuss the general design before blowing it up.

Absolutely. Never meant to be the absolute and final design. It is a first proposal that in my opinion is close to the use of standard algorithms and therefor has a major advantage over designs where I need to provide template member types in structs that evaluate to bool_constant types based on SFINAE or constraints.

Can you do one of the simpler temporary solutions for #863 like defining a concept and immediately expanding on that?

Sure.

@rrahn rrahn requested a review from smehringer August 21, 2019 11:16
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from ad6b4c8 to 2952562 Compare August 21, 2019 11:17
@rrahn
Copy link
Contributor Author

rrahn commented Aug 21, 2019

So I moved the functionality to core/detail/pack_algorithm and also moved the already existing for_each functionality to this file.

@rrahn rrahn force-pushed the feature/type_list_algorithms branch 4 times, most recently from 16a46f2 to 76af1e6 Compare August 27, 2019 15:43
@rrahn
Copy link
Contributor Author

rrahn commented Aug 27, 2019

@smehringer ping

@smehringer
Copy link
Member

Travis was failing so I did not review this before

@rrahn
Copy link
Contributor Author

rrahn commented Aug 28, 2019

you can ignore jenkins for this PR.

Copy link
Member

@smehringer smehringer left a comment

Choose a reason for hiding this comment

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

You introduce code in commit 1 & 2 that you delete again in commit 3. I guess you plan to squash this or ? It if confusing to review commit by commit because it is hard to track if there are other changes than those of altering your feature again. It would be nice if you split these changes from the feature.

I did not review type traits that often so I am a littel confused about the naming.
When do we call something _type? (all_of_type)

include/seqan3/core/type_list/traits.hpp Outdated Show resolved Hide resolved
test/unit/core/type_list_test.cpp Outdated Show resolved Hide resolved
test/snippet/core/detail/all_of_pack.cpp Outdated Show resolved Hide resolved
test/snippet/core/detail/all_of_type_list.cpp Outdated Show resolved Hide resolved
test/snippet/core/detail/all_of_type_list_2.cpp Outdated Show resolved Hide resolved
@@ -30,27 +30,27 @@ int main()
static_assert(std::is_same_v<id_t, std::type_identity<type>>, "id is of type std::type_identity<type>");

if constexpr(std::is_same_v<type, bool>)
debug_stream << "bool";
seqan3::debug_stream << "bool";
Copy link
Member

Choose a reason for hiding this comment

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

remove using namespace seqan3; in line 8

@@ -0,0 +1,54 @@
#include <iostream>
Copy link
Member

Choose a reason for hiding this comment

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

you are using debug stream, do you need this include?

@rrahn
Copy link
Contributor Author

rrahn commented Aug 28, 2019

You introduce code in commit 1 & 2 that you delete again in commit 3. I guess you plan to squash this or ? It if confusing to review commit by commit because it is hard to track if there are other changes than those of altering your feature again. It would be nice if you split these changes from the feature.

yes. I'll squash this.

I did not review type traits that often so I am a littel confused about the naming.
When do we call something _type? (all_of_type)

Well, we need to somehow distinguish all_of for type lists and parameter packs since we do not use different namespaces as it is done in the type_list traits at the moment. Accordingly, the _type version denotes the overload for type_lists.

@smehringer
Copy link
Member

Well, we need to somehow distinguish all_of for type lists and parameter packs since we do not use different namespaces as it is done in the type_list traits at the moment. Accordingly, the _type version denotes the overload for type_lists.

Ugh... But we usually put _type behind names that denote a type using iterator_type = ... . It is confusing that a type trait is now called _type :(
Is this a naming we use throughout the library already or did we recently intrduce/dicuss this and I missed it?

@rrahn
Copy link
Contributor Author

rrahn commented Sep 4, 2019

Ugh... But we usually put _type behind names that denote a type using iterator_type = ... . It is confusing that a type trait is now called _type :(
Is this a naming we use throughout the library already or did we recently intrduce/dicuss this and I missed it?

This was already introduced for for_each_type, which was a name used to iterate over types in a type list or template parameter pack. We also had this for parameter packs called for_each_value. I removed the value suffix for the parameter packs, but we need a different name for the type versions otherwise there is an ambiguous overload. Note, that these functions are not purely type_traits and as such are not added to type_list/traits, where we explicitly introduced namespaces. Since this is pure detail and only for developers I guess the naming is not so relevant. In general, I am not a fan of using the suffix type in a class name as well, since all classes are types. We had something like for_each_in_type_list but that was to verbose for the use cases we considered. So if you like you can add a discussion item for the next strategy meeting but my feeling is that it is not worth it to have a lengthy discussion about it.

@rrahn rrahn force-pushed the feature/type_list_algorithms branch 3 times, most recently from c61b57d to 5506dab Compare September 4, 2019 19:12
@smehringer
Copy link
Member

I agree that if it is strictly detail it's not worth a lengthy discussion.
One more suggestion though, what about type_list_for_each/type_list_all_of? It would mimic the namespace you mentioned for type traits (that I assume would be `type_list::all_of``).
If you disagree, I will just review the PR again.

@rrahn
Copy link
Contributor Author

rrahn commented Sep 9, 2019

@smehringer ping

@smehringer
Copy link
Member

smehringer commented Sep 9, 2019

I was waiting for an answer but I guess this means you disagree?

@smehringer
Copy link
Member

since I am second reviewer now maybe someone else should review this first

@smehringer smehringer requested review from marehr and removed request for smehringer September 10, 2019 10:52
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from 5506dab to b90611f Compare September 10, 2019 16:17
@rrahn
Copy link
Contributor Author

rrahn commented Sep 13, 2019

@marehr ping

@marehr
Copy link
Member

marehr commented Sep 16, 2019

@marehr ping

Sorry for the late response, I have the feeling that this PR would be best discussed in person.

@rrahn
Copy link
Contributor Author

rrahn commented Sep 16, 2019

Sorry for the late response, I have the feeling that this PR would be best discussed in person.

Ok, then please put it on the card for next Monday discussion. I do agree that we need to be certain about the design and that here are multiple cornerstones here.

@marehr
Copy link
Member

marehr commented Sep 16, 2019

Yep. I added a card https://github.com/orgs/seqan/projects/4#card-26492576

@rrahn rrahn force-pushed the feature/type_list_algorithms branch 2 times, most recently from 2dfd2dd to 9f5fe60 Compare September 26, 2019 15:05
@joshuak94
Copy link
Contributor

@rrahn What's the status here?

@rrahn
Copy link
Contributor Author

rrahn commented Oct 1, 2019

@joshuak94 I am waiting on the review, From POV this is done.

@rrahn rrahn force-pushed the feature/type_list_algorithms branch 2 times, most recently from e3ae56b to 89f5e47 Compare October 2, 2019 21:54
Copy link
Member

@marehr marehr left a comment

Choose a reason for hiding this comment

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

🤸‍♂️ Thank you.The code looks good to me. Just some smaller and sometimes a tiny bit bigger smaller naming and documentation stuff, as well as proposal to remove tuple support. 🤸‍♀️ Took me longer than 1am xD

include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
test/snippet/core/detail/all_of_in_pack.cpp Outdated Show resolved Hide resolved
test/snippet/core/detail/all_of_in_pack.cpp Outdated Show resolved Hide resolved
test/unit/core/detail/pack_algorithm_test.cpp Outdated Show resolved Hide resolved
test/unit/core/detail/pack_algorithm_test.cpp Outdated Show resolved Hide resolved
test/unit/core/detail/pack_algorithm_test.cpp Outdated Show resolved Hide resolved
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from 89f5e47 to af042b6 Compare October 4, 2019 11:34
@rrahn rrahn requested a review from marehr October 4, 2019 11:35
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from af042b6 to e620aa1 Compare October 4, 2019 11:36
Copy link
Member

@marehr marehr left a comment

Choose a reason for hiding this comment

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

This is a very happy @marehr; Just some little tiny stuff left.

test/snippet/core/detail/all_of_in_pack.cpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from e620aa1 to a6b3f61 Compare October 7, 2019 14:03
@rrahn rrahn requested a review from marehr October 7, 2019 14:03
Copy link
Member

@marehr marehr left a comment

Choose a reason for hiding this comment

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

😽 LGTM 💋

include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
@rrahn rrahn requested a review from smehringer October 7, 2019 17:54
Copy link
Member

@smehringer smehringer left a comment

Choose a reason for hiding this comment

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

some minor stuff

include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
include/seqan3/core/detail/pack_algorithm.hpp Show resolved Hide resolved
// all_of
//-----------------------------------------------------------------------------

/*!\brief Tests whether a given predicate evaluates to `true` for each element in a parameter pack.
Copy link
Member

Choose a reason for hiding this comment

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

This may be just personal flavour, but you do not call this function by passing a parameter pack but you call it by passing a variable number of values? You just use the parameter pack to capture this. Or am I wrong?
So this description might be misleading?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A function parameter pack is a function parameter that accepts zero or more function arguments.

From cppreference. I adapted the brief to use exactly this expression function parameter pack. Would that be clearer? At least it follows the definition more closely?

*/
template <typename unary_function_t, typename ...pack_t>
//!\cond
requires (std::invocable<unary_function_t, pack_t> && ... && true)
Copy link
Member

Choose a reason for hiding this comment

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

isn't this sufficient:

Suggested change
requires (std::invocable<unary_function_t, pack_t> && ... && true)
requires (std::invocable<unary_function_t, pack_t> && ...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But it results in the exactly same result. But of course this can be expressed so as well.

Copy link
Member

Choose a reason for hiding this comment

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

um yes, thats why I was wandering about the unneccessary && true, does it have any purpose then?

include/seqan3/core/detail/pack_algorithm.hpp Outdated Show resolved Hide resolved
@rrahn rrahn force-pushed the feature/type_list_algorithms branch from a6b3f61 to 225023f Compare October 8, 2019 13:56
@rrahn rrahn requested a review from smehringer October 8, 2019 13:56
@rrahn
Copy link
Contributor Author

rrahn commented Oct 8, 2019

Failing build is unrelated.

@smehringer smehringer merged commit 19ab4cd into seqan:master Oct 9, 2019
@rrahn rrahn deleted the feature/type_list_algorithms branch October 11, 2019 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants