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

Add semialphabet any #981

Merged
merged 2 commits into from
May 21, 2019
Merged

Add semialphabet any #981

merged 2 commits into from
May 21, 2019

Conversation

sarahet
Copy link
Member

@sarahet sarahet commented May 16, 2019

No description provided.

@codecov
Copy link

codecov bot commented May 16, 2019

Codecov Report

Merging #981 into master will increase coverage by 0.02%.
The diff coverage is 100%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
...ude/seqan3/alphabet/composite/semialphabet_any.hpp 100% <100%> (ø)
include/seqan3/core/bit_manipulation.hpp 92.3% <0%> (-1.03%) ⬇️
...qan3/alignment/pairwise/edit_distance_unbanded.hpp 82.97% <0%> (-0.81%) ⬇️
include/seqan3/io/stream/debug_stream.hpp 94.44% <0%> (-0.48%) ⬇️
.../pairwise/execution/alignment_executor_two_way.hpp 97.05% <0%> (-0.09%) ⬇️
...e/seqan3/alignment/matrix/alignment_coordinate.hpp 100% <0%> (ø) ⬆️
include/seqan3/io/alignment_file/input.hpp 100% <0%> (ø) ⬆️
include/seqan3/alphabet/nucleotide/dna5.hpp 100% <0%> (ø) ⬆️
include/seqan3/alphabet/aminoacid/aa10li.hpp 100% <0%> (ø) ⬆️
include/seqan3/alphabet/nucleotide/rna4.hpp 100% <0%> (ø) ⬆️
... and 30 more

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 495f648...852e4af. Read the comment docs.

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.

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.
Copy link
Member

Choose a reason for hiding this comment

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

Good description 👍

Copy link
Member

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.
*
Copy link
Member

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
*/
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
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).

Copy link
Member

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)
Copy link
Member

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;
Copy link
Member

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

Copy link
Member Author

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 😄

Copy link
Member

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.

Copy link
Member

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()

}
};

}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
}
} // 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;
Copy link
Member

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.

Copy link
Member

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
*
Copy link
Member

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()
Copy link
Member

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.

@h-2 h-2 merged commit 8c66b64 into seqan:master May 21, 2019
@sarahet sarahet mentioned this pull request May 24, 2019
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.

2 participants