-
Notifications
You must be signed in to change notification settings - Fork 83
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
Add semialphabet any #981
Add semialphabet any #981
Conversation
78d4dbd
to
8a93925
Compare
Codecov Report
@@ Coverage Diff @@
## master #981 +/- ##
==========================================
+ Coverage 96.38% 96.41% +0.02%
==========================================
Files 181 181
Lines 6635 6633 -2
==========================================
Hits 6395 6395
+ Misses 240 238 -2
Continue to review full report at Codecov.
|
8a93925
to
bda43fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good! Mostly remarks regarding the example!
* of the same size. | ||
* It is therefore possible to convert the semialphabet_any into an alphabet type that is not the original | ||
* alphabet type. However, this should either be avoided or used with care as no warnings are given when attempting | ||
* to convert the semialphabet_any into a type that is not comparable to the original alphabet type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good description 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would maybe add one more sentence:
The main advantage of using this data structure is to reduce instantiation of templates when using multiple alphabets of the same size and either their character representation is not important or they are reified at a later point in the program.
* It is therefore possible to convert the semialphabet_any into an alphabet type that is not the original | ||
* alphabet type. However, this should either be avoided or used with care as no warnings are given when attempting | ||
* to convert the semialphabet_any into a type that is not comparable to the original alphabet type. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add before the snippet
### Example
* to convert the semialphabet_any into a type that is not comparable to the original alphabet type. | ||
* | ||
* \snippet test/snippet/alphabet/composite/semialphabet_any.cpp example | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add:
\see https://en.wikipedia.org/wiki/Type_erasure
\see https://en.wikipedia.org/wiki/Reification_(computer_science)
|
||
//!\brief Construct semialphabet_any from alphabet of the same size | ||
template <Semialphabet other_alph_t> | ||
requires alphabet_size_v<other_alph_t> == size |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requires alphabet_size_v<other_alph_t> == size | |
//!\cond | |
requires (alphabet_size_v<other_alph_t> == size) | |
//!\endcond |
We need to hide the requires clause from doxygen and we need to also put () around most terms now (because clang requires this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also for the conversion operator
//!\brief Construct semialphabet_any from alphabet of the same size | ||
template <Semialphabet other_alph_t> | ||
requires alphabet_size_v<other_alph_t> == size | ||
semialphabet_any(other_alph_t const other) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make both the constructor and the conversion operator explicit
. This will at least prevent the conversions from happening automatically and force people to use static_cast
(or direct initialisation).
requires alphabet_size_v<other_alph_t> == size | ||
semialphabet_any(other_alph_t const other) | ||
{ | ||
using seqan3::to_rank; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this weird stuff is not required anymore since #943
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not required because it needs to be replaced by something else? Or not required and should just work without?
Because I get an error when I remove it and this PR is so huge I can not immediately find an answer 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Write seqan3::
before the calls in the line below instead. This is only necessary if you have member functions of the same name. Otherwise you can omit the seqan3::
entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Write seqan3:: before the calls in the line below instead.
Just before to_rank()
} | ||
}; | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
} // namespace seqan3 |
💅
// This is possible however should be used with care since there will be no warning given when attempting to convert | ||
// a semialphabet_any into an alphabet that is not the original alphabet. This may lead to errors when transforming | ||
// the semialphabet_any into an alphabet type that is not comparable to the original type. | ||
aa10murphy_vector v4 = v2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, but this is what we want people not to do!
I would maybe make the example like this (roughly sketched and not tested, bad grammar)
// print is a template and gets instantiated two times,
// because the behaviour is different for both types
template <typename rng_t>
void print(rng_t && r)
{
seqan3::debug_stream << r << '\n';
}
// algorithm is not a template, only one instance is generated by the compiler;
// type information is encoded via a run-time parameter
void algorithm(std::vector<semialphabet_any<10>> & r, bool is_murphy)
{
// a silly algorithm example that replaces rank 0 with rank 1:
for (auto & v : r)
if (seqan3::to_rank(v) == 0)
seqan3::assign_rank_to(1, v);
// here we reify the type for printing
if (is_murphy)
print(v | seqan3::view::convert<aa10murphy>);
else
print(v | seqan3::view::convert<aa10li>);
}
// two instances of algo_pre exist; they type erase the different arguments to the same type
// and encode the type information as a run-time parameter
void algo_pre(aa10li_vector const & v)
{
seqan3::semialphabet_any<10> tmp = v | seqan3::view::convert<semialphabet_any<10>>;
algo(tmp, false);
}
void algo_pre(aa10murphy_vector const & v)
{
seqan3::semialphabet_any<10> tmp = v | seqan3::view::convert<semialphabet_any<10>>;
algo(tmp, true);
}
int main()
{
seqan33::aa10li_vector v1 {...};
algo_pre(v1);
seqan3::aa10murphy_vector v2 {...};
algo_pre(v2);
}
And explanation:
The example illustrates how we can reduce the usage of templates
(or the amount of different instantiations) via type erasure. Having only
one function generated for `algo()` is the only benefit of using `semialphabet_any`
here. Of course this only makes sense for your application if the part of the program
that is agnostic of the character representation (your equivalent of `algo()`) is
substantially larger than the specific parts – and if compile-time and/or
size of the exectuble are a concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW: we don't use using namespace seqan3;
in the snippets anymore...
* \ingroup composite | ||
* \implements seqan3::TriviallyCopyable | ||
* \implements seqan3::StandardLayout | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
\implements seqan3::Semialphabet
//!\brief Enable conversion of semialphabet_any into other (semi-)alphabet of the same size | ||
template <Semialphabet other_alph_t> | ||
requires alphabet_size_v<other_alph_t> == size | ||
operator other_alph_t() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
your conversion operator needs to be const
-qualified, otherwise you imply that the function will change the object and it won't be possible to call it in a const-context, like in view::convert
.
bda43fe
to
852e4af
Compare
No description provided.