Revised RFC on range design for D2

Bill Baxter wbaxter at gmail.com
Fri Sep 12 07:02:12 PDT 2008


On Fri, Sep 12, 2008 at 2:44 PM, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> In wake of the many excellent comments and suggestions made here, I made one
> more pass through the draft proposal for ranges.
>
> http://ssli.ee.washington.edu/~aalexand/d/tmp/std_range.html
>
> There are some comments in red illustrating some uncertainties (not all),
> and the names of the primitives have been updated. Bicycle shed galore! But
> don't forget to comment on the reactor as well :o).
>

Looking better!

I disagree with this:
"""
User code may pair iterators wrongly to create meaningless ranges. For
example, given collections a and b of the same type, a.begin to
b.begin makes no sense as a range, yet both the compiler and the
runtime are hard-pressed in rejecting such mistakes. Such problems are
often (though not always) avoided if range is the primitive.
"""

You can just as easily create nonsensical ranges using before() and
after().  And I don't recall ever making the mistake of mixing up one
container's begin() with another's end().

I disagree here too:
"""
A bidirectional range models the natural way of iterating a doubly-linked list.
"""
It maybe provides an efficient way to implement many algorithms on a
doubly linked list.  But to say it implements the natural way of
iterating one is a big stretch.

I was about to argue that "head" should be "value" and "toe" should be
"tvalue" on the grounds that most of the time iteration with a range
going to be all about the head.  For all intents and purposes it *is*
the current value.  Another benefit is that the terminology of
".value" generalizes to plain iterators well.  And it may be useful
for users to create iterators that support some but not all of the
range interface (like .value and .next).  The name .value doesn't work
for the random access concept so well, but if you are using the random
access range like a forward range it does, and if you aren't using it
like a forward range,  then you'd use r[0] anyway instead of r.value.

However, that was mainly motivated by the feeling that if we ever do
have iterators, that having to make the dereference op be .head would
look fatally silly.  But I think eventually if you get out of the
iterator mindset, and think of ranges as everything, then it's not so
silly to describe an iterator as a poor castrated half-range that
knows where its head is, where it's next is, but isn't so sure about
the rest.  So I think I can live with .head.  Even for iterators if we
end up having them.

But I do have some suggestions nonetheless!  Marked with ==> below.

-- Universal --
r.done
r.init

--- Input : Universal ---
e=r.head
e=r.next
r1=r.release  ==> r.transfer?  Release sounds like ref counting (e.g. in COM)
                          Also seems like r.transfer(r1) could make
implementation more efficient.
                          Or perhaps make it a .swap like STL.  Maybe
you have something against .swap?

-- Output : Universal --
r.put(e)

-- Forward : Input, (optional) Output  --
r1 = r
r.head = e
t=r.after(s)

-- Bidirectional : Forward --
e = r.toe
r.toe = e
r.reduce           ==> r.retreat  -- aka "pull back"
t = r.before(s)

-- Random access : Bidirectional --
l = r.length
e = r[n]
r[n] = e
r1 = r[n1..n2]
------------

Just those two!

--bb


More information about the Digitalmars-d-announce mailing list