[iterator] generator_iterator vs. function_input_iterator

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
Hi,

There seems to be two nearly equivalent components in Boost.Iterator:
generator_iterator (moved from Boost.Utility) and
function_input_iterator. Both are input iterators wrapping a function
object, which result is used as the dereferenced value. The difference is:

- generator_iterator always creates an instance of the element type
while function_input_iterator does that lazily;
- function_input_iterator uses result_of while generator_iterator relies
on C++03 T::result_type
- equality comparison is different: generator_iterators compares equal
if both refer to the same generator and cached element instances are
equal while function_input_iterator uses an additional state (which can
be viewed as an index) for comparison instead of the cached element.

So basically, they are the same thing. generator_iterator looks a bit
more dated and IMHO its comparison implementation is not as robust as
that of function_input_iterator, so maybe we should deprecate it?

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
Andrey Semashev wrote:
> There seems to be two nearly equivalent components in Boost.Iterator:
> generator_iterator (moved from Boost.Utility) and function_input_iterator.

`function_input_iterator`'s implementation looks better than that of
`generator_iterator`. However, the name of the former is not appealing.
"generate" is a standard word to Range enthusiasts -- it is used like
`generate(non_pure_func) | take(10)`.

Thus, I would like to deprecate `generator_iterator` first and then rename
`function_input_iterator` to `generator_iterator`.

Regards,
Michel

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
On 08/31/17 19:16, Michel Morin via Boost wrote:

> Andrey Semashev wrote:
>> There seems to be two nearly equivalent components in Boost.Iterator:
>> generator_iterator (moved from Boost.Utility) and function_input_iterator.
>
> `function_input_iterator`'s implementation looks better than that of
> `generator_iterator`. However, the name of the former is not appealing.
> "generate" is a standard word to Range enthusiasts -- it is used like
> `generate(non_pure_func) | take(10)`.
>
> Thus, I would like to deprecate `generator_iterator` first and then rename
> `function_input_iterator` to `generator_iterator`.

Well, there is function_output_iterator also, I kind of like the
duality. I guess we could make generator_iterator an alias in C++11,
although I'm a bit worried if this could cause backward compatibility
for users if they upgrade from a release with the old generator_iterator.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On 8/31/17 9:16 AM, Michel Morin via Boost wrote:

> Andrey Semashev wrote:
>> There seems to be two nearly equivalent components in Boost.Iterator:
>> generator_iterator (moved from Boost.Utility) and function_input_iterator.
>
> `function_input_iterator`'s implementation looks better than that of
> `generator_iterator`. However, the name of the former is not appealing.
> "generate" is a standard word to Range enthusiasts -- it is used like
> `generate(non_pure_func) | take(10)`.
>
> Thus, I would like to deprecate `generator_iterator` first and then rename
> `function_input_iterator` to `generator_iterator`.

Hmmmm - I'm thinking that silently changing the functionality of a
component 12? years old to something "nearly" equivalent is a really bad
idea.  How can one know that this wouldn't break old code in a way
that's just about impossible to track down.

If you wanted to create a "better" naming scheme and map them to the
original names with typedef or using, that would be much better and have
no potential for inflicting damage on innocent bystanders, that would be
OK.  But then you'd have to update the documentation which is another
task.  Actually, I question the value in this kind of change anyway.
There's nothing which would prevent users who are annoyed by this from
just including a couple of typedefs/usings in their own code.  This
looks like cosmetic surgery where the quest for perfection is the enemy
of getting the best result.

Robert Ramey

> Regards,
> Michel
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
On 31-08-17 20:18, Robert Ramey via Boost wrote:
> Hmmmm - I'm thinking that silently changing the functionality of a
> component 12? years old to something "nearly" equivalent is a really
> bad idea.  How can one know that this wouldn't break old code in a way
> that's just about impossible to track down.

+1


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Andrey Semashev wrote:

> Well, there is function_output_iterator also, I kind of like the duality.

Each name has supporters ;)

> I'm a bit worried if this could cause backward compatibility for users
> if they upgrade from a release with the old generator_iterator.

Non-default constructors for function_input_iterator and generator_iterator are
incompatible; function_input_iterator has binary constructors and
generator_iterator has unary constructors. Even if we add unary
constructors that take only generator to function_input_iterator, they
are incompatible; function_input_iterator accepts lvalue objects or
function pointers and
generator_iterator accepts pointers to objects but not function pointers.

So, when upgrading from old generator_iterator to new one (i.e.
function_input_iterator), there should be compilation failures.
We can add the following constructor to help migration:

  class new_generator_iterator {
      new_generator_iterator(PointerToObject)
      {
          static_assert(false,
              "The implementation of generator_iterator has changed. "
              "Please consult the documentation to see how to update
the code.");
      }
  };

However, if users of old generator_iterator rely on behaviors of the eager
generation and of the equality operators, then the migration is hard to achieve.
OK... I drop this idea.

Range users may not care much about the name of underlying iterators;
it would be OK if range constructs have standard names. I'll submit a PR
that implements `generation` (the name `generate` is already used for
range algorithms, so I use the name `generation` which is used in the
Oven range library) to Boost.Range, which looks like

  template <typename Func, typename Count>
  inline auto generation(Func& f, Count cnt)
  {
      return make_iterator_range(
          make_function_input_iterator(f, Count())
        , make_function_input_iterator(f, cnt)
      );
  }

  template <typename Func>
  inline auto
  generation(Func& f)
  {
      return make_iterator_range(
          make_function_input_iterator(f, infinite{})
        , make_function_input_iterator(f, infinite{})
      );
  }

Regards,
Michel

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [iterator] generator_iterator vs. function_input_iterator

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Robert Ramey wrote:
> Hmmmm - I'm thinking that silently changing the functionality
> of a component 12? years old to something "nearly" equivalent
> is a really bad idea.  How can one know that this wouldn't
> break old code in a way that's just about impossible to track down.

Thanks for the comment.
I thought that if the following are all satisfied then it would be
worth the change. But as described below, some of them are not satisfied.

1. `old_xxxx` is unanimously better name than `new_xxxx`.
2. `new_xxxx` has better implementation and new users should use the `new_xxxx`.
3. If there is any behavioral change, that should not be silent (that should
result in compilation failures).
4. Easy to update old codes.

- It seems that 1 is not true for other than range enthusiasts.
- `generator_iterator` is easy to be misused. For example, this function
    void print_random_numbers(int n)
    {
        auto it = make_generator_iterator(std::random_device{});
        for (int i = 0; i < n; ++i) {
              cout << *it << endl;
        }
    }
  consumes n+1 random numbers (the last random number is thrown away).
  `function_input_iterator` avoids such behaviors and consumes just
  n random numbers. So I think 2 is satisfied.
- 3 is satisfied, but 4 is not satisfied unless we introduce
  `generator_iterator_v1` (that is, renamed old `generator_iterator`).

Regards,
Michel

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost