-
Notifications
You must be signed in to change notification settings - Fork 107
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
Implement iterate algorithms #101
base: develop
Are you sure you want to change the base?
Conversation
Template parameter names imply that this algorithm operates on a range of output iterators. But there's no such thing. Output iterators aren't required to have equality comparison. The algorithm actually requires a range of forward iterators. Also is it really a major improvement over the following? std::generate(first, last, [&init, op]{ return init = op(init); }) |
Hi @grisumbras - thanks for the feedback! I appreciate your concerns and I'd love to arrive at a design that you think is better 🙂
I used
It seems like there is no clear practice that's being followed throughout the codebase. I would argue that the type of iterator should be checked by the interface, not simply held in the name. To that end - does a boost wrapper around the iterator concepts exist? They could be added as constraints and checked where available.
I'll start by stating that that's a matter of opinion, but I would argue that it is an improvement. This library explicitly targets C++03 where lambdas aren't available - it's a clear win over writing a function object in that case. Even in standards where lambdas exist though, for me this API more clearly captures intent than |
A few observations:
The question "is iterate preferable to generate?" has a similar flavour to the question "is accumulate preferable to for_each?" In both cases the same effect as the "dedicated" function can be achieved with the "more general" function and stateful lambda expressions. But I consider both accumulate and iterate to be important upgrades in intent and in composability. Both also allow a more declarative coding style. iterate is an unfold, just as accumulate is a fold, and comparing iterate to accumulate (and contrasting with generate/for_each) is useful. iterate wins over generate in a couple of important ways:
One last thing: the name iterate is taken from Haskell. I haven't conducted a survey of other languages to see what the prevailing name of least surprise, if any, would be. |
The pattern is evidently that the name of the template parameter type corresponds to the named requirement. And regardless, using With regards to the name of the functions. |
I was misunderstanding the concern on iterator requirements - I've updated that to a state that I think is correct.
I have not been able to find a boost macro for move, unfortunately. If one exists, I'll happily pepper it throughout as I agree that that makes the behavior more flexible.
No - just a code style I've been trying out. (Roughly, the idea is that if prefix
I did some digging on this and couldn't find any other languages with similar named facilities where it wasn't called |
Problem: - There is no algorithm that generalizes `std::iota`. Filling a range 2 elements at a time is hard, more complex patterns are increasingly difficult. Solution: - Implement `iterate` and `iterate_n` which fill a range based on the execution of a binary operation which takes the previous value.
An update on the naming: As far as I can tell, this algorithm is only named in functional language standard libraries. Haskell, Clojure, OCaml, and Scala (and perhaps more, those were the ones that I found) have this algorithm and all of them call it |
Problem:
std::iota
. Filling a range 2elements at a time is hard, more complex patterns are increasingly
difficult.
Solution:
Implement
iterate
anditerate_n
which fill a range based on theexecution of a binary operation which takes the previous value.
h/t to @elbeno for suggesting the algorithm and some feedback on the interface