Safe Cursors and Ranges

Steven Schveighoffer schveiguy at yahoo.com
Thu Aug 26 08:48:24 PDT 2010


On Thu, 26 Aug 2010 11:17:32 -0400, Pillsy <pillsbury at gmail.com> wrote:

> Steven Schveighoffer Wrote:
>
>> On Thu, 26 Aug 2010 10:18:51 -0400, Pillsy <pillsbury at gmail.com>
>> wrote:
> [...]
>> > The key idea is that these cursors aren't a primitive part of a
>> > range; instead, they take a range and add a position *inside*
>> > the range. They're a perfect fit for all those "three-legged"
>> > operations out there because they actually have three legs.
> [...]
>> The 'three-legged' cursor as you propose was an early idea of
>> mine too.
>
> If you don't mind me asking, what made you give up on it?

A cursor that refers to one element is much more efficient to pass  
around/copy.  Plus the extra baggage was not needed in dcollections -- any  
operations you perform on a cursor besides changing the value require you  
to have the container also (i.e. a cursor is mainly a parameter to the  
container).  I don't know how this relates to three-legged algorithms and  
straight ranges+cursors, dcollections ranges+cursors would need some extra  
binding support to use them, since you need the container to create a  
range based on two cursors.

>
>> My view is that a cursor should be separate from a range, and a
>> range should either be able to tell if a cursor is part of it (@safe)
>> or be told  that a cursor is a part of it (@system or @trusted).
>
> What's the advantage of not holding on to the range as part of the
> cursor? I'm more focused on the typical value-type ranges, but I'm
> not seeing a lot of need for cursors that have lives independent of
> underlying ranges. Is the concern just one of more frequent
> invalidation?

Because some cursors do not need the hard reference, it is trivial to tell  
whether such cursors belong to a range.  For instance, it's trivial to  
tell that a pointer is part of an array.  So a cursor for an array would  
not need to refer the range it belongs to.

For instance, if I have an array, and a cursor in that array, it's trivial  
for an allBefore operation to determine that the cursor is a member of the  
array.  Now, let's say we have two slices that contain the same cursor, in  
your scheme, in order to use one cursor against the other range, you need  
to recompose the cursor, which seems unnecessarily awkward.  Such a scheme  
is not possible on other ranges, but that just means those ranges don't  
support safe calls for allBefore and the like.  For those ranges, a  
3-legged type would be appropriate, but the 3-legged thing could be a  
combination of a cursor and a range, with the cursor proven to be part of  
the range -- an invariant of the 3-legged type.

Having a cursor point to exactly one element allows more flexibility,  
because you could use a cursor with multiple ranges.  It also decouples  
the cursor from a range that might be superfluous information.  For  
example, if I want to store a link list element cursor so I can change it  
later, why do I also have to carry around the baggage of the range it came  
from?

One of the drawbacks is the cursor cannot move to other elements or alter  
topology, it's strictly a reference-only.  Another reason to have the  
3-legged type.

>
> IME, three-legged operations are fairly common, but four- and more-
> legged operations which can't be easily decomposed into consecutive
> three-legged operations are very uncommon.

I have no experience with three-legged operations.  I just looked at  
cursors from the point of view of reference to a single element.  Such an  
ability is important for a container library.

I can see such an ability being important for simple operations as well,  
not just algorithms.

> What I'm thinking is that cursors aren't skinny ranges, they're ranges
> that are even fatter. You simply wouldn't use one where a range
> would suffice. Allowing questions about whether a range contains a
> cursor or not strikes me as just buying trouble.

But you don't always care if a cursor is a part of a range.  For example,  
to change or refer to a specific element of a range, why do you need to  
refer to the range also?  The composition of a range and cursor together  
can be guarded by @system or @trusted indicating the type system is taking  
your word for it, but in some cases, it can be proven without assumption  
(i.e. arrays).

I don't have a problem with defining such a three-legged type, but can we  
call it something besides a cursor?  Not that I have a trademark or  
anything, but it would be really confusing to have it mean two different  
things depending on context :)

As I said, I can see utility in having a three-legged beast that combines  
a cursor and a range, but I see value in having a simple one-element  
cursor as well.

-Steve


More information about the Digitalmars-d mailing list