Skip to content

Add ranget drop and skip methods #4347

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

Merged

Conversation

romainbrenguier
Copy link
Contributor

This adds two utility methods to ranget which I would find useful.
For instance we could iterate on a ranget with a while loop instead of a range-for: while(!range.empty()) { ....; range.drop(1); ...}

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • [na] The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • [na] My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • [na] White-space or formatting changes outside the feature-related changed lines are in commits of their own.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

⚠️
This PR failed Diffblue compatibility checks (cbmc commit: 73cbe05).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103580996
Status will be re-evaluated on next push.
Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)

  • the author is not in the list of contributors (e.g. first-time contributors).

  • the compatibility was already broken by an earlier merge.

src/util/range.h Outdated
void drop(std::size_t count)
{
std::size_t i = 0;
while(i < count && begin_value != end_value)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit pick, but wouldn't this make for a very nice for loop? As is, it looks a bit like assembler programming.

src/util/range.h Outdated
/// Return an new range containing the same elements except for the first
/// \p count elements.
/// If the range has fewer elements, returns an empty range.
ranget<iteratort> skip(std::size_t count) const
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't find the names drop and skip entirely intuitive. I am wondering whether using longer, more unambiguous names would be better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe. I'm open to suggestions. drop is also used by range-v3, so we should maybe keep this one.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Whatever is used elsewhere I'm happy with, just stick with that terminology then.

Copy link
Contributor

Choose a reason for hiding this comment

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

drop and skip are both fine names, but they are kinda synonyms. I think we should choose one or the other, but not both. The name used in .net's linq is skip - https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skip?view=netframework-4.7.2
The name in haskell would be drop - http://zvon.org/other/haskell/Outputprelude/drop_f.html
Because C++ supports overloading we could actually have 3 different overloads, all with the same name if we wanted. A mutation overload, a const & overload and an r-value overload. I would suggest keeping just a const & and the r-value overload, in order to reduce the need to reason about mutation.

}
THEN("Skip first 2 elements")
{
auto range = make_range(list).skip(2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be better to have a test where you also test the original range to make that indeed skip does not modify anything, just generates a copy.

@romainbrenguier
Copy link
Contributor Author

@smowton I made a slight change to the drop function: by returning a Boolean we can avoid some redundant iterator comparison and for instance write while(range.drop(1)) { ... }

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

⚠️
This PR failed Diffblue compatibility checks (cbmc commit: 39146d2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103603097
Status will be re-evaluated on next push.
Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)

  • the author is not in the list of contributors (e.g. first-time contributors).

  • the compatibility was already broken by an earlier merge.

src/util/range.h Outdated
/// \return true if the range still contains element after the drop
bool drop(std::size_t count)
{
for(std::size_t i = 0; i < count; ++i)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You don't actually need i, do you? for( ; count > 0; --count) ... would do the trick.

@romainbrenguier romainbrenguier force-pushed the feature/range-drop branch 2 times, most recently from ac09326 to d6b5acb Compare March 8, 2019 11:52
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

⚠️
This PR failed Diffblue compatibility checks (cbmc commit: ac09326).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103676521
Status will be re-evaluated on next push.
Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)

  • the author is not in the list of contributors (e.g. first-time contributors).

  • the compatibility was already broken by an earlier merge.

@romainbrenguier romainbrenguier force-pushed the feature/range-drop branch 2 times, most recently from 2f9f9e2 to e6cb484 Compare March 8, 2019 13:58
/// \return true if the range still contains element after the drop
ranget<iteratort> drop(std::size_t count) &&
{
for(; count > 0 && begin_value != end_value; --count)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Could this be defined in terms of std::advance and std::distance? I think you could advance the begin iterator by the std::min of count and the distance between the begin and the end iterators.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe, but I don't know if it's worth it. Some distance functions work by iterating from the current position to the end, so using that plus advance would end up being less efficient.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

⚠️
This PR failed Diffblue compatibility checks (cbmc commit: 2f9f9e2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103685752
Status will be re-evaluated on next push.
Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)

  • the author is not in the list of contributors (e.g. first-time contributors).

  • the compatibility was already broken by an earlier merge.

@romainbrenguier
Copy link
Contributor Author

Following @thomasspriggs suggestions, I made the two versions be named drop and return a new range, the difference between the two is that one works on ranges that are rvalues

This is useful for advancing the range without having to manipulate the
private `begin_value` field.

We have two versions of this, both return a new range, but one is used
when the range on which the method is called can be moved.
This tests that these operations behave as expected and gives examples
on how to use them.
This can avoid some copies of the iterators.
@romainbrenguier romainbrenguier merged commit d91b397 into diffblue:develop Mar 8, 2019
@romainbrenguier romainbrenguier deleted the feature/range-drop branch March 8, 2019 15:34
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 962c9f4).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103695677

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.

5 participants