Peter Alexander wrote:
On 21/07/10 6:33 PM, Andrei Alexandrescu wrote:
Peter Alexander wrote:
== Quote from Walter Bright (newshou...@digitalmars.com)'s article
If some algorithms used ranges and others used iterators, the
poor programmer
would find himself then obliged to implement both interfaces for
each container.

This makes no sense.

I don't understand why you see ranges and iterators as conflicting
concepts. The cursors/iterators are for referring to individual
elements, and ranges are for specifying iterations over a sequence.

There aren't two competing interfaces here. If your interface
requires a range of elements, you use a range. If it only needs a
single element, you use a cursor.

For example, sort would always take a range, as it is sorting a
range, not a single element. I *do not* propose that we start
writing sort(Iter begin, Iter end) as that is much less flexible
than a range, and as you say, it is much harder to validate.

An example of an algorithm that would take a cursor is
insertBefore. There is no reason for it to accept a range, because
you are not traversing elements. You just want to insert something
before some single point in the range.

This contradicts the assertion that there's no competition between
iterators and ranges. Clearly they share at least some turf. Though I
agree "insert before this given element" is sensible, I don't think
"insert before this range" is not. Besides, with ranges the notion is
easier to generalize to "insert after this range" and "replace this
range with another range". Arguably "insert after this one element" and
"replace this one element with a range" are less general.

There are benefits to having cursors. There are also disadvantages:
interfaces and implementations get bloated, users get aggravated,
documentation gets thicker, conceptual overhead rises, design options
multiply without necessity ("should I provide replace with one iterator
in addition to replace with a range?"), writing code becomes more
painful ("heck, I need a range here but I only have an iterator (or vice
versa), I need to insert this extra construct here to build the other")
etc. etc. I understand you want to advocate iterators so you chose to
not discuss the disaadvantages, but any plan that would ignore them
would not be complete.

Well, yes, you could say they share some turf, but that's common when one can be defined in terms of the other. e.g.

  double norm(Matrix m);
  double norm(Vector v);

Here, vectors are just special cases of matrices, and the matrix version will handle norms of vectors just fine. norm(Matrix) is undeniably more general. Yet, every linear algebra library I've seen would provide both of these, because it's inconvenient (and unintuitive) to have to write

  norm(Matrix(myVector));

I refute this analogy. Matrices and vectors are different beasts - there's no obviously defined dot product for a matrix etc. I know there are counter-arguments to this, to which I have counter-counter-arguments to which I'm sure there are counter-counter-counter arguments and so on, so I suggest we continue discussing iterators and not the validity of this analogy.

I also find it unintuitive to write insertBefore(Range). Why is it asking me for a range when it's going to ignore everything but the first element?

Well a pragmatic answer is that you only have ranges in a consistently range-based interface.

Why can't I just pass in the single position I want to insert before? The same applies for insertAfter.

Because D's containers don't define a notion of "a single position".

In the case of replacing ranges with other ranges, I don't think there is any need for a cursor version. If you want to replace a cursor, you just dereference and write to it. Having a function to do that would be totally unnecessary.

Maybe you want to replace one element with an entire range.


Andrei

Reply via email to